| 1 | /* |
| 2 | * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 20 | * or visit www.oracle.com if you need additional information or have any |
| 21 | * questions. |
| 22 | */ |
| 23 | |
| 24 | #ifndef SHARE_JVMCI_JVMCICODEINSTALLER_HPP |
| 25 | #define SHARE_JVMCI_JVMCICODEINSTALLER_HPP |
| 26 | |
| 27 | #include "code/debugInfoRec.hpp" |
| 28 | #include "code/exceptionHandlerTable.hpp" |
| 29 | #include "code/nativeInst.hpp" |
| 30 | #include "jvmci/jvmci.hpp" |
| 31 | #include "jvmci/jvmciEnv.hpp" |
| 32 | |
| 33 | #if INCLUDE_AOT |
| 34 | class RelocBuffer : public StackObj { |
| 35 | enum { stack_size = 1024 }; |
| 36 | public: |
| 37 | RelocBuffer() : _size(0), _buffer(0) {} |
| 38 | ~RelocBuffer(); |
| 39 | void ensure_size(size_t bytes); |
| 40 | void set_size(size_t bytes); |
| 41 | address begin() const; |
| 42 | size_t size() const { return _size; } |
| 43 | private: |
| 44 | size_t _size; |
| 45 | char _static_buffer[stack_size]; |
| 46 | char *_buffer; |
| 47 | }; |
| 48 | |
| 49 | class CodeInstaller; |
| 50 | |
| 51 | class AOTOopRecorder : public OopRecorder { |
| 52 | public: |
| 53 | AOTOopRecorder(CodeInstaller* code_inst, Arena* arena = NULL, bool deduplicate = false); |
| 54 | |
| 55 | virtual int find_index(Metadata* h); |
| 56 | virtual int find_index(jobject h); |
| 57 | int nr_meta_refs() const; |
| 58 | jobject meta_element(int pos) const; |
| 59 | |
| 60 | private: |
| 61 | void record_meta_ref(jobject ref, int index); |
| 62 | |
| 63 | GrowableArray<jobject>* _meta_refs; |
| 64 | |
| 65 | CodeInstaller* _code_inst; |
| 66 | }; |
| 67 | #endif // INCLUDE_AOT |
| 68 | |
| 69 | class CodeMetadata { |
| 70 | public: |
| 71 | CodeMetadata() {} |
| 72 | |
| 73 | CodeBlob* get_code_blob() const { return _cb; } |
| 74 | |
| 75 | PcDesc* get_pc_desc() const { return _pc_desc; } |
| 76 | int get_nr_pc_desc() const { return _nr_pc_desc; } |
| 77 | |
| 78 | u_char* get_scopes_desc() const { return _scopes_desc; } |
| 79 | int get_scopes_size() const { return _nr_scopes_desc; } |
| 80 | |
| 81 | #if INCLUDE_AOT |
| 82 | RelocBuffer* get_reloc_buffer() { return &_reloc_buffer; } |
| 83 | AOTOopRecorder* get_oop_recorder() { return _oop_recorder; } |
| 84 | #endif |
| 85 | |
| 86 | ExceptionHandlerTable* get_exception_table() { return _exception_table; } |
| 87 | |
| 88 | ImplicitExceptionTable* get_implicit_exception_table() { return _implicit_exception_table; } |
| 89 | |
| 90 | void set_pc_desc(PcDesc* desc, int count) { |
| 91 | _pc_desc = desc; |
| 92 | _nr_pc_desc = count; |
| 93 | } |
| 94 | |
| 95 | void set_scopes(u_char* scopes, int size) { |
| 96 | _scopes_desc = scopes; |
| 97 | _nr_scopes_desc = size; |
| 98 | } |
| 99 | |
| 100 | #if INCLUDE_AOT |
| 101 | void set_oop_recorder(AOTOopRecorder* recorder) { |
| 102 | _oop_recorder = recorder; |
| 103 | } |
| 104 | #endif |
| 105 | |
| 106 | void set_exception_table(ExceptionHandlerTable* table) { |
| 107 | _exception_table = table; |
| 108 | } |
| 109 | |
| 110 | void set_implicit_exception_table(ImplicitExceptionTable* table) { |
| 111 | _implicit_exception_table = table; |
| 112 | } |
| 113 | |
| 114 | private: |
| 115 | CodeBlob* _cb; |
| 116 | PcDesc* _pc_desc; |
| 117 | int _nr_pc_desc; |
| 118 | |
| 119 | u_char* _scopes_desc; |
| 120 | int _nr_scopes_desc; |
| 121 | |
| 122 | #if INCLUDE_AOT |
| 123 | RelocBuffer _reloc_buffer; |
| 124 | AOTOopRecorder* _oop_recorder; |
| 125 | #endif |
| 126 | ExceptionHandlerTable* _exception_table; |
| 127 | ImplicitExceptionTable* _implicit_exception_table; |
| 128 | }; |
| 129 | |
| 130 | /* |
| 131 | * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod. |
| 132 | */ |
| 133 | class CodeInstaller : public StackObj { |
| 134 | friend class JVMCIVMStructs; |
| 135 | private: |
| 136 | enum MarkId { |
| 137 | VERIFIED_ENTRY = 1, |
| 138 | UNVERIFIED_ENTRY = 2, |
| 139 | OSR_ENTRY = 3, |
| 140 | EXCEPTION_HANDLER_ENTRY = 4, |
| 141 | DEOPT_HANDLER_ENTRY = 5, |
| 142 | INVOKEINTERFACE = 6, |
| 143 | INVOKEVIRTUAL = 7, |
| 144 | INVOKESTATIC = 8, |
| 145 | INVOKESPECIAL = 9, |
| 146 | INLINE_INVOKE = 10, |
| 147 | POLL_NEAR = 11, |
| 148 | POLL_RETURN_NEAR = 12, |
| 149 | POLL_FAR = 13, |
| 150 | POLL_RETURN_FAR = 14, |
| 151 | CARD_TABLE_ADDRESS = 15, |
| 152 | CARD_TABLE_SHIFT = 16, |
| 153 | HEAP_TOP_ADDRESS = 17, |
| 154 | HEAP_END_ADDRESS = 18, |
| 155 | NARROW_KLASS_BASE_ADDRESS = 19, |
| 156 | NARROW_OOP_BASE_ADDRESS = 20, |
| 157 | CRC_TABLE_ADDRESS = 21, |
| 158 | LOG_OF_HEAP_REGION_GRAIN_BYTES = 22, |
| 159 | INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 23, |
| 160 | INVOKE_INVALID = -1 |
| 161 | }; |
| 162 | |
| 163 | Arena _arena; |
| 164 | JVMCIEnv* _jvmci_env; |
| 165 | |
| 166 | JVMCIPrimitiveArray _data_section_handle; |
| 167 | JVMCIObjectArray _data_section_patches_handle; |
| 168 | JVMCIObjectArray _sites_handle; |
| 169 | #ifndef PRODUCT |
| 170 | JVMCIObjectArray _comments_handle; |
| 171 | #endif |
| 172 | JVMCIPrimitiveArray _code_handle; |
| 173 | JVMCIObject _word_kind_handle; |
| 174 | |
| 175 | CodeOffsets _offsets; |
| 176 | |
| 177 | jint _code_size; |
| 178 | jint _total_frame_size; |
| 179 | jint _orig_pc_offset; |
| 180 | jint _parameter_count; |
| 181 | jint _constants_size; |
| 182 | |
| 183 | bool _has_wide_vector; |
| 184 | |
| 185 | MarkId _next_call_type; |
| 186 | address _invoke_mark_pc; |
| 187 | |
| 188 | CodeSection* _instructions; |
| 189 | CodeSection* _constants; |
| 190 | |
| 191 | OopRecorder* _oop_recorder; |
| 192 | DebugInformationRecorder* _debug_recorder; |
| 193 | Dependencies* _dependencies; |
| 194 | ExceptionHandlerTable _exception_handler_table; |
| 195 | ImplicitExceptionTable _implicit_exception_table; |
| 196 | |
| 197 | bool _immutable_pic_compilation; // Installer is called for Immutable PIC compilation. |
| 198 | |
| 199 | static ConstantOopWriteValue* _oop_null_scope_value; |
| 200 | static ConstantIntValue* _int_m1_scope_value; |
| 201 | static ConstantIntValue* _int_0_scope_value; |
| 202 | static ConstantIntValue* _int_1_scope_value; |
| 203 | static ConstantIntValue* _int_2_scope_value; |
| 204 | static LocationValue* _illegal_value; |
| 205 | |
| 206 | jint pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCIObject method, JVMCI_TRAPS); |
| 207 | void pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS); |
| 208 | void pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject constant, JVMCI_TRAPS); |
| 209 | void pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS); |
| 210 | void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS); |
| 211 | void pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject method, jint pc_offset, JVMCI_TRAPS); |
| 212 | void pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS); |
| 213 | |
| 214 | JVMCIObjectArray sites() { return _sites_handle; } |
| 215 | JVMCIPrimitiveArray code() { return _code_handle; } |
| 216 | JVMCIPrimitiveArray data_section() { return _data_section_handle; } |
| 217 | JVMCIObjectArray data_section_patches() { return _data_section_patches_handle; } |
| 218 | #ifndef PRODUCT |
| 219 | JVMCIObjectArray comments() { return _comments_handle; } |
| 220 | #endif |
| 221 | JVMCIObject word_kind() { return _word_kind_handle; } |
| 222 | |
| 223 | public: |
| 224 | |
| 225 | CodeInstaller(JVMCIEnv* jvmci_env, bool immutable_pic_compilation) : _arena(mtJVMCI), _jvmci_env(jvmci_env), _immutable_pic_compilation(immutable_pic_compilation) {} |
| 226 | |
| 227 | #if INCLUDE_AOT |
| 228 | JVMCI::CodeInstallResult gather_metadata(JVMCIObject target, JVMCIObject compiled_code, CodeMetadata& metadata, JVMCI_TRAPS); |
| 229 | #endif |
| 230 | JVMCI::CodeInstallResult install(JVMCICompiler* compiler, |
| 231 | JVMCIObject target, |
| 232 | JVMCIObject compiled_code, |
| 233 | CodeBlob*& cb, |
| 234 | JVMCIObject installed_code, |
| 235 | FailedSpeculation** failed_speculations, |
| 236 | char* speculations, |
| 237 | int speculations_len, |
| 238 | JVMCI_TRAPS); |
| 239 | |
| 240 | JVMCIEnv* jvmci_env() { return _jvmci_env; } |
| 241 | JVMCIRuntime* runtime() { return _jvmci_env->runtime(); } |
| 242 | |
| 243 | static address runtime_call_target_address(oop runtime_call); |
| 244 | static VMReg get_hotspot_reg(jint jvmciRegisterNumber, JVMCI_TRAPS); |
| 245 | static bool is_general_purpose_reg(VMReg hotspotRegister); |
| 246 | |
| 247 | const OopMapSet* oopMapSet() const { return _debug_recorder->_oopmaps; } |
| 248 | |
| 249 | protected: |
| 250 | Location::Type get_oop_type(JVMCIObject value); |
| 251 | ScopeValue* get_scope_value(JVMCIObject value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second, JVMCI_TRAPS); |
| 252 | MonitorValue* get_monitor_value(JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS); |
| 253 | |
| 254 | void* record_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS); |
| 255 | #ifdef _LP64 |
| 256 | narrowKlass record_narrow_metadata_reference(CodeSection* section, address dest, JVMCIObject constant, JVMCI_TRAPS); |
| 257 | #endif |
| 258 | |
| 259 | // extract the fields of the HotSpotCompiledCode |
| 260 | void initialize_fields(JVMCIObject target, JVMCIObject compiled_code, JVMCI_TRAPS); |
| 261 | void initialize_dependencies(JVMCIObject compiled_code, OopRecorder* oop_recorder, JVMCI_TRAPS); |
| 262 | |
| 263 | int estimate_stubs_size(JVMCI_TRAPS); |
| 264 | |
| 265 | // perform data and call relocation on the CodeBuffer |
| 266 | JVMCI::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, JVMCI_TRAPS); |
| 267 | |
| 268 | void assumption_NoFinalizableSubclass(JVMCIObject assumption); |
| 269 | void assumption_ConcreteSubtype(JVMCIObject assumption); |
| 270 | void assumption_LeafType(JVMCIObject assumption); |
| 271 | void assumption_ConcreteMethod(JVMCIObject assumption); |
| 272 | void assumption_CallSiteTargetValue(JVMCIObject assumption, JVMCI_TRAPS); |
| 273 | |
| 274 | void site_Safepoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS); |
| 275 | void site_Infopoint(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS); |
| 276 | void site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS); |
| 277 | void site_DataPatch(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS); |
| 278 | void site_Mark(CodeBuffer& buffer, jint pc_offset, JVMCIObject site, JVMCI_TRAPS); |
| 279 | void site_ExceptionHandler(jint pc_offset, JVMCIObject site); |
| 280 | |
| 281 | OopMap* create_oop_map(JVMCIObject debug_info, JVMCI_TRAPS); |
| 282 | |
| 283 | VMReg getVMRegFromLocation(JVMCIObject location, int total_frame_size, JVMCI_TRAPS); |
| 284 | |
| 285 | /** |
| 286 | * Specifies the level of detail to record for a scope. |
| 287 | */ |
| 288 | enum ScopeMode { |
| 289 | // Only record a method and BCI |
| 290 | BytecodePosition, |
| 291 | // Record a method, bci and JVM frame state |
| 292 | FullFrame |
| 293 | }; |
| 294 | |
| 295 | int map_jvmci_bci(int bci); |
| 296 | |
| 297 | void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, bool return_oop, JVMCI_TRAPS); |
| 298 | void record_scope(jint pc_offset, JVMCIObject debug_info, ScopeMode scope_mode, JVMCI_TRAPS) { |
| 299 | record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, JVMCIENV); |
| 300 | } |
| 301 | void record_scope(jint pc_offset, JVMCIObject position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, JVMCI_TRAPS); |
| 302 | void record_object_value(ObjectValue* sv, JVMCIObject value, GrowableArray<ScopeValue*>* objects, JVMCI_TRAPS); |
| 303 | |
| 304 | GrowableArray<ScopeValue*>* record_virtual_objects(JVMCIObject debug_info, JVMCI_TRAPS); |
| 305 | |
| 306 | int estimateStubSpace(int static_call_stubs); |
| 307 | }; |
| 308 | |
| 309 | #endif // SHARE_JVMCI_JVMCICODEINSTALLER_HPP |
| 310 | |