43 } 44 45 46 void StubAssembler::set_frame_size(int size) { 47 if (_frame_size == no_frame_size) { 48 _frame_size = size; 49 } 50 assert(_frame_size == size, "can't change the frame size"); 51 } 52 53 54 void StubAssembler::set_num_rt_args(int args) { 55 if (_num_rt_args == 0) { 56 _num_rt_args = args; 57 } 58 assert(_num_rt_args == args, "can't change the number of args"); 59 } 60 61 // Implementation of Runtime1 62 63 bool Runtime1::_is_initialized = false; 64 CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids]; 65 const char *Runtime1::_blob_names[] = { 66 RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME) 67 }; 68 69 #ifndef PRODUCT 70 // statistics 71 int Runtime1::_generic_arraycopy_cnt = 0; 72 int Runtime1::_primitive_arraycopy_cnt = 0; 73 int Runtime1::_oop_arraycopy_cnt = 0; 74 int Runtime1::_arraycopy_slowcase_cnt = 0; 75 int Runtime1::_new_type_array_slowcase_cnt = 0; 76 int Runtime1::_new_object_array_slowcase_cnt = 0; 77 int Runtime1::_new_instance_slowcase_cnt = 0; 78 int Runtime1::_new_multi_array_slowcase_cnt = 0; 79 int Runtime1::_monitorenter_slowcase_cnt = 0; 80 int Runtime1::_monitorexit_slowcase_cnt = 0; 81 int Runtime1::_patch_code_slowcase_cnt = 0; 82 int Runtime1::_throw_range_check_exception_count = 0; 83 int Runtime1::_throw_index_exception_count = 0; 84 int Runtime1::_throw_div0_exception_count = 0; 85 int Runtime1::_throw_null_pointer_exception_count = 0; 86 int Runtime1::_throw_class_cast_exception_count = 0; 87 int Runtime1::_throw_incompatible_class_change_error_count = 0; 88 int Runtime1::_throw_array_store_exception_count = 0; 89 int Runtime1::_throw_count = 0; 90 #endif 91 92 BufferBlob* Runtime1::_buffer_blob = NULL; 93 94 // Simple helper to see if the caller of a runtime stub which 95 // entered the VM has been deoptimized 96 97 static bool caller_is_deopted() { 98 JavaThread* thread = JavaThread::current(); 99 RegisterMap reg_map(thread, false); 100 frame runtime_frame = thread->last_frame(); 101 frame caller_frame = runtime_frame.sender(®_map); 102 assert(caller_frame.is_compiled_frame(), "must be compiled"); 103 return caller_frame.is_deoptimized_frame(); 104 } 105 106 // Stress deoptimization 107 static void deopt_caller() { 108 if ( !caller_is_deopted()) { 109 JavaThread* thread = JavaThread::current(); 110 RegisterMap reg_map(thread, false); 111 frame runtime_frame = thread->last_frame(); 112 frame caller_frame = runtime_frame.sender(®_map); 113 // bypass VM_DeoptimizeFrame and deoptimize the frame directly 114 Deoptimization::deoptimize_frame(thread, caller_frame.id()); 115 assert(caller_is_deopted(), "Must be deoptimized"); 116 } 117 } 118 119 120 BufferBlob* Runtime1::get_buffer_blob() { 121 // Allocate code buffer space only once 122 BufferBlob* blob = _buffer_blob; 123 if (blob == NULL) { 124 // setup CodeBuffer. Preallocate a BufferBlob of size 125 // NMethodSizeLimit plus some extra space for constants. 126 int code_buffer_size = desired_max_code_buffer_size() + desired_max_constant_size(); 127 blob = BufferBlob::create("Compiler1 temporary CodeBuffer", 128 code_buffer_size); 129 guarantee(blob != NULL, "must create initial code buffer"); 130 _buffer_blob = blob; 131 } 132 return _buffer_blob; 133 } 134 135 void Runtime1::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) { 136 // Preinitialize the consts section to some large size: 137 int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo)); 138 char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); 139 code->insts()->initialize_shared_locs((relocInfo*)locs_buffer, 140 locs_buffer_size / sizeof(relocInfo)); 141 code->initialize_consts_size(desired_max_constant_size()); 142 // Call stubs + deopt/exception handler 143 code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) + 144 LIR_Assembler::exception_handler_size + 145 LIR_Assembler::deopt_handler_size); 146 } 147 148 149 void Runtime1::generate_blob_for(StubID id) { 150 assert(0 <= id && id < number_of_ids, "illegal stub id"); 151 ResourceMark rm; 152 // create code buffer for code storage 153 CodeBuffer code(get_buffer_blob()->instructions_begin(), 154 get_buffer_blob()->instructions_size()); 155 156 setup_code_buffer(&code, 0); 157 158 // create assembler for code generation 159 StubAssembler* sasm = new StubAssembler(&code, name_for(id), id); 160 // generate code for runtime stub 161 OopMapSet* oop_maps; 162 oop_maps = generate_code_for(id, sasm); 163 assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, 164 "if stub has an oop map it must have a valid frame size"); 165 166 #ifdef ASSERT 167 // Make sure that stubs that need oopmaps have them 168 switch (id) { 169 // These stubs don't need to have an oopmap 170 case dtrace_object_alloc_id: 171 case g1_pre_barrier_slow_id: 172 case g1_post_barrier_slow_id: 173 case slow_subtype_check_id: 174 case fpu2long_stub_id: 175 case unwind_exception_id: 176 #ifndef TIERED 187 } 188 #endif 189 190 // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) 191 sasm->align(BytesPerWord); 192 // make sure all code is in code buffer 193 sasm->flush(); 194 // create blob - distinguish a few special cases 195 CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), 196 &code, 197 CodeOffsets::frame_never_safe, 198 sasm->frame_size(), 199 oop_maps, 200 sasm->must_gc_arguments()); 201 // install blob 202 assert(blob != NULL, "blob must exist"); 203 _blobs[id] = blob; 204 } 205 206 207 void Runtime1::initialize() { 208 // Warning: If we have more than one compilation running in parallel, we 209 // need a lock here with the current setup (lazy initialization). 210 if (!is_initialized()) { 211 _is_initialized = true; 212 213 // platform-dependent initialization 214 initialize_pd(); 215 // generate stubs 216 for (int id = 0; id < number_of_ids; id++) generate_blob_for((StubID)id); 217 // printing 218 #ifndef PRODUCT 219 if (PrintSimpleStubs) { 220 ResourceMark rm; 221 for (int id = 0; id < number_of_ids; id++) { 222 _blobs[id]->print(); 223 if (_blobs[id]->oop_maps() != NULL) { 224 _blobs[id]->oop_maps()->print(); 225 } 226 } 227 } 228 #endif 229 } 230 } 231 232 233 CodeBlob* Runtime1::blob_for(StubID id) { 234 assert(0 <= id && id < number_of_ids, "illegal stub id"); 235 if (!is_initialized()) initialize(); 236 return _blobs[id]; 237 } 238 239 240 const char* Runtime1::name_for(StubID id) { 241 assert(0 <= id && id < number_of_ids, "illegal stub id"); 242 return _blob_names[id]; 243 } 244 245 const char* Runtime1::name_for_address(address entry) { 246 for (int id = 0; id < number_of_ids; id++) { 247 if (entry == entry_for((StubID)id)) return name_for((StubID)id); 248 } 249 250 #define FUNCTION_CASE(a, f) \ 251 if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f 252 253 FUNCTION_CASE(entry, os::javaTimeMillis); 254 FUNCTION_CASE(entry, os::javaTimeNanos); 255 FUNCTION_CASE(entry, SharedRuntime::OSR_migration_end); | 43 } 44 45 46 void StubAssembler::set_frame_size(int size) { 47 if (_frame_size == no_frame_size) { 48 _frame_size = size; 49 } 50 assert(_frame_size == size, "can't change the frame size"); 51 } 52 53 54 void StubAssembler::set_num_rt_args(int args) { 55 if (_num_rt_args == 0) { 56 _num_rt_args = args; 57 } 58 assert(_num_rt_args == args, "can't change the number of args"); 59 } 60 61 // Implementation of Runtime1 62 63 CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids]; 64 const char *Runtime1::_blob_names[] = { 65 RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME) 66 }; 67 68 #ifndef PRODUCT 69 // statistics 70 int Runtime1::_generic_arraycopy_cnt = 0; 71 int Runtime1::_primitive_arraycopy_cnt = 0; 72 int Runtime1::_oop_arraycopy_cnt = 0; 73 int Runtime1::_arraycopy_slowcase_cnt = 0; 74 int Runtime1::_new_type_array_slowcase_cnt = 0; 75 int Runtime1::_new_object_array_slowcase_cnt = 0; 76 int Runtime1::_new_instance_slowcase_cnt = 0; 77 int Runtime1::_new_multi_array_slowcase_cnt = 0; 78 int Runtime1::_monitorenter_slowcase_cnt = 0; 79 int Runtime1::_monitorexit_slowcase_cnt = 0; 80 int Runtime1::_patch_code_slowcase_cnt = 0; 81 int Runtime1::_throw_range_check_exception_count = 0; 82 int Runtime1::_throw_index_exception_count = 0; 83 int Runtime1::_throw_div0_exception_count = 0; 84 int Runtime1::_throw_null_pointer_exception_count = 0; 85 int Runtime1::_throw_class_cast_exception_count = 0; 86 int Runtime1::_throw_incompatible_class_change_error_count = 0; 87 int Runtime1::_throw_array_store_exception_count = 0; 88 int Runtime1::_throw_count = 0; 89 #endif 90 91 // Simple helper to see if the caller of a runtime stub which 92 // entered the VM has been deoptimized 93 94 static bool caller_is_deopted() { 95 JavaThread* thread = JavaThread::current(); 96 RegisterMap reg_map(thread, false); 97 frame runtime_frame = thread->last_frame(); 98 frame caller_frame = runtime_frame.sender(®_map); 99 assert(caller_frame.is_compiled_frame(), "must be compiled"); 100 return caller_frame.is_deoptimized_frame(); 101 } 102 103 // Stress deoptimization 104 static void deopt_caller() { 105 if ( !caller_is_deopted()) { 106 JavaThread* thread = JavaThread::current(); 107 RegisterMap reg_map(thread, false); 108 frame runtime_frame = thread->last_frame(); 109 frame caller_frame = runtime_frame.sender(®_map); 110 // bypass VM_DeoptimizeFrame and deoptimize the frame directly 111 Deoptimization::deoptimize_frame(thread, caller_frame.id()); 112 assert(caller_is_deopted(), "Must be deoptimized"); 113 } 114 } 115 116 117 void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) { 118 assert(0 <= id && id < number_of_ids, "illegal stub id"); 119 ResourceMark rm; 120 // create code buffer for code storage 121 CodeBuffer code(buffer_blob->instructions_begin(), 122 buffer_blob->instructions_size()); 123 124 Compilation::setup_code_buffer(&code, 0); 125 126 // create assembler for code generation 127 StubAssembler* sasm = new StubAssembler(&code, name_for(id), id); 128 // generate code for runtime stub 129 OopMapSet* oop_maps; 130 oop_maps = generate_code_for(id, sasm); 131 assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, 132 "if stub has an oop map it must have a valid frame size"); 133 134 #ifdef ASSERT 135 // Make sure that stubs that need oopmaps have them 136 switch (id) { 137 // These stubs don't need to have an oopmap 138 case dtrace_object_alloc_id: 139 case g1_pre_barrier_slow_id: 140 case g1_post_barrier_slow_id: 141 case slow_subtype_check_id: 142 case fpu2long_stub_id: 143 case unwind_exception_id: 144 #ifndef TIERED 155 } 156 #endif 157 158 // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) 159 sasm->align(BytesPerWord); 160 // make sure all code is in code buffer 161 sasm->flush(); 162 // create blob - distinguish a few special cases 163 CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), 164 &code, 165 CodeOffsets::frame_never_safe, 166 sasm->frame_size(), 167 oop_maps, 168 sasm->must_gc_arguments()); 169 // install blob 170 assert(blob != NULL, "blob must exist"); 171 _blobs[id] = blob; 172 } 173 174 175 void Runtime1::initialize(BufferBlob* blob) { 176 // platform-dependent initialization 177 initialize_pd(); 178 // generate stubs 179 for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id); 180 // printing 181 #ifndef PRODUCT 182 if (PrintSimpleStubs) { 183 ResourceMark rm; 184 for (int id = 0; id < number_of_ids; id++) { 185 _blobs[id]->print(); 186 if (_blobs[id]->oop_maps() != NULL) { 187 _blobs[id]->oop_maps()->print(); 188 } 189 } 190 } 191 #endif 192 } 193 194 195 CodeBlob* Runtime1::blob_for(StubID id) { 196 assert(0 <= id && id < number_of_ids, "illegal stub id"); 197 return _blobs[id]; 198 } 199 200 201 const char* Runtime1::name_for(StubID id) { 202 assert(0 <= id && id < number_of_ids, "illegal stub id"); 203 return _blob_names[id]; 204 } 205 206 const char* Runtime1::name_for_address(address entry) { 207 for (int id = 0; id < number_of_ids; id++) { 208 if (entry == entry_for((StubID)id)) return name_for((StubID)id); 209 } 210 211 #define FUNCTION_CASE(a, f) \ 212 if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f 213 214 FUNCTION_CASE(entry, os::javaTimeMillis); 215 FUNCTION_CASE(entry, os::javaTimeNanos); 216 FUNCTION_CASE(entry, SharedRuntime::OSR_migration_end); |