1 /* 2 * Copyright (c) 2023, 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 25 #include "precompiled.hpp" 26 #include "cds/archiveBuilder.hpp" 27 #include "cds/cdsAccess.hpp" 28 #include "cds/cdsConfig.hpp" 29 #include "cds/filemap.hpp" 30 #include "cds/heapShared.hpp" 31 #include "cds/metaspaceShared.hpp" 32 #include "classfile/stringTable.hpp" 33 #include "logging/log.hpp" 34 #include "logging/logStream.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "memory/universe.hpp" 37 #include "memory/virtualspace.hpp" 38 #include "oops/instanceKlass.hpp" 39 40 size_t _cached_code_size = 0; 41 42 bool CDSAccess::can_generate_cached_code(address addr) { 43 if (CDSConfig::is_dumping_final_static_archive()) { 44 return ArchiveBuilder::is_active() && ArchiveBuilder::current()->has_been_archived(addr); 45 } else { 46 // Old CDS+AOT workflow. 47 return MetaspaceShared::is_in_shared_metaspace(addr); 48 } 49 } 50 51 bool CDSAccess::can_generate_cached_code(InstanceKlass* ik) { 52 if (CDSConfig::is_dumping_final_static_archive()) { 53 if (!ArchiveBuilder::is_active()) { 54 return false; 55 } 56 ArchiveBuilder* builder = ArchiveBuilder::current(); 57 if (!builder->has_been_archived((address)ik)) { 58 return false; 59 } 60 InstanceKlass* buffered_ik = builder->get_buffered_addr(ik); 61 if (ik->is_shared_unregistered_class()) { 62 return false; 63 } 64 return true; 65 } else { 66 // Old CDS+AOT workflow. 67 return ik->is_shared() && !ik->is_shared_unregistered_class(); 68 } 69 } 70 71 uint CDSAccess::delta_from_shared_address_base(address addr) { 72 if (CDSConfig::is_dumping_final_static_archive()) { 73 assert(ArchiveBuilder::is_active(), "must be"); 74 ArchiveBuilder* builder = ArchiveBuilder::current(); 75 address requested_addr = builder->to_requested(builder->get_buffered_addr(addr)); 76 return (uint)pointer_delta(requested_addr, (address)SharedBaseAddress, 1); 77 } else { 78 // Old CDS+AOT workflow. 79 return (uint)pointer_delta(addr, (address)SharedBaseAddress, 1); 80 } 81 } 82 83 Method* CDSAccess::method_in_cached_code(Method* m) { 84 if (CDSConfig::is_dumping_final_static_archive()) { 85 assert(ArchiveBuilder::is_active(), "must be"); 86 ArchiveBuilder* builder = ArchiveBuilder::current(); 87 return builder->to_requested(builder->get_buffered_addr(m)); 88 } else { 89 // Old CDS+AOT workflow. 90 return m; 91 } 92 } 93 94 #if INCLUDE_CDS_JAVA_HEAP 95 int CDSAccess::get_archived_object_permanent_index(oop obj) { 96 return HeapShared::get_archived_object_permanent_index(obj); 97 } 98 99 oop CDSAccess::get_archived_object(int permanent_index) { 100 return HeapShared::get_archived_object(permanent_index); 101 } 102 103 static void test_cds_heap_access_api_for_object(oop obj) { 104 LogStreamHandle(Info, cds, jit) log; 105 106 obj->print_on(&log); 107 log.cr(); 108 109 int n = CDSAccess::get_archived_object_permanent_index(obj); // call this when -XX:+StoreCachedCode 110 if (n < 0) { 111 log.print_cr("*** This object is not in CDS archive"); 112 } else { 113 log.print_cr("CDSAccess::get_archived_object_permanent_index(s) = %d", n); 114 oop archived_obj = CDSAccess::get_archived_object(n); // call this when -XX:+LoadCachedCode 115 if (archived_obj == obj || archived_obj == HeapShared::orig_to_scratch_object(obj)) { 116 log.print_cr("CDSAccess::get_archived_object(%d) returns the same object, as expected", n); 117 } else { 118 log.print_cr("Error!!! CDSAccess::get_archived_object(%d) returns an unexpected object", n); 119 if (archived_obj == nullptr) { 120 log.print_cr("--> null"); 121 } else { 122 archived_obj->print_on(&log); 123 log.cr(); 124 } 125 } 126 } 127 } 128 129 // TEMP: examples for using the CDSAccess::get_archived_object_permanent_index() and CDSAccess::get_archived_object() 130 // APIs for the AOT compiler. 131 132 void CDSAccess::test_heap_access_api() { 133 ResourceMark rm; 134 const char* tests[] = { 135 "", 136 "null", 137 "NARROW", 138 "not in cds", 139 nullptr, 140 }; 141 142 LogStreamHandle(Info, cds, jit) log; 143 144 int i; 145 for (i = 0; tests[i] != nullptr; i++) { 146 EXCEPTION_MARK; 147 log.print_cr("Test %d ======================================== \"%s\"", i, tests[i]); 148 oop s = StringTable::intern(tests[i], CHECK); 149 test_cds_heap_access_api_for_object(s); 150 } 151 152 log.print_cr("Test %d ======================================== Universe::null_ptr_exception_instance()", i); 153 test_cds_heap_access_api_for_object(Universe::null_ptr_exception_instance()); 154 } 155 156 // new workflow only 157 void* CDSAccess::allocate_from_code_cache(size_t size) { 158 assert(CDSConfig::is_dumping_final_static_archive(), "must be"); 159 return (void*)ArchiveBuilder::cc_region_alloc(size); 160 } 161 162 size_t CDSAccess::get_cached_code_size() { 163 return _cached_code_size; 164 } 165 166 void CDSAccess::set_cached_code_size(size_t sz) { 167 _cached_code_size = sz; 168 } 169 170 void CDSAccess::set_pointer(address* ptr, address value) { 171 ArchiveBuilder* builder = ArchiveBuilder::current(); 172 if (value != nullptr && !builder->is_in_buffer_space(value)) { 173 value = builder->get_buffered_addr(value); 174 } 175 *ptr = value; 176 ArchivePtrMarker::mark_pointer(ptr); 177 } 178 179 bool CDSAccess::map_cached_code(ReservedSpace rs) { 180 FileMapInfo* static_mapinfo = FileMapInfo::current_info(); 181 assert(UseSharedSpaces && static_mapinfo != nullptr, "must be"); 182 return static_mapinfo->map_cached_code_region(rs); 183 } 184 185 #endif // INCLUDE_CDS_JAVA_HEAP