comparison src/share/vm/jvmci/jvmciEnv.cpp @ 21559:be896a1983c0

recast all Graal native code as JVMCI code (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Thu, 28 May 2015 15:36:48 +0200
parents src/share/vm/graal/graalEnv.cpp@2e35a4ea22ac
children df9d2375512a
comparison
equal deleted inserted replaced
21558:d563baeca9df 21559:be896a1983c0
1 /*
2 * Copyright (c) 1999, 2011, 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 "jvmci/jvmciEnv.hpp"
27 #include "classfile/systemDictionary.hpp"
28 #include "classfile/vmSymbols.hpp"
29 #include "code/scopeDesc.hpp"
30 #include "runtime/sweeper.hpp"
31 #include "compiler/compileBroker.hpp"
32 #include "compiler/compileLog.hpp"
33 #include "compiler/compilerOracle.hpp"
34 #include "interpreter/linkResolver.hpp"
35 #include "memory/allocation.inline.hpp"
36 #include "memory/oopFactory.hpp"
37 #include "memory/universe.inline.hpp"
38 #include "oops/methodData.hpp"
39 #include "oops/objArrayKlass.hpp"
40 #include "prims/jvmtiExport.hpp"
41 #include "runtime/init.hpp"
42 #include "runtime/reflection.hpp"
43 #include "runtime/sharedRuntime.hpp"
44 #include "utilities/dtrace.hpp"
45 #include "jvmci/jvmciRuntime.hpp"
46 #include "jvmci/jvmciJavaAccess.hpp"
47
48 JVMCIEnv::JVMCIEnv(CompileTask* task, int system_dictionary_modification_counter) {
49 _task = task;
50 _system_dictionary_modification_counter = system_dictionary_modification_counter;
51 {
52 // Get Jvmti capabilities under lock to get consistent values.
53 MutexLocker mu(JvmtiThreadState_lock);
54 _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
55 _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
56 _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions();
57 }
58 }
59
60 // ------------------------------------------------------------------
61 // Note: the logic of this method should mirror the logic of
62 // constantPoolOopDesc::verify_constant_pool_resolve.
63 bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) {
64 if (accessing_klass->oop_is_objArray()) {
65 accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass();
66 }
67 if (!accessing_klass->oop_is_instance()) {
68 return true;
69 }
70
71 if (resolved_klass->oop_is_objArray()) {
72 // Find the element klass, if this is an array.
73 resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
74 }
75 if (resolved_klass->oop_is_instance()) {
76 return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
77 }
78 return true;
79 }
80
81 // ------------------------------------------------------------------
82 KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass,
83 constantPoolHandle& cpool,
84 Symbol* sym,
85 bool require_local) {
86 JVMCI_EXCEPTION_CONTEXT;
87
88 // Now we need to check the SystemDictionary
89 if (sym->byte_at(0) == 'L' &&
90 sym->byte_at(sym->utf8_length()-1) == ';') {
91 // This is a name from a signature. Strip off the trimmings.
92 // Call recursive to keep scope of strippedsym.
93 TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
94 sym->utf8_length()-2,
95 CHECK_(KlassHandle()));
96 return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local);
97 }
98
99 Handle loader(THREAD, (oop)NULL);
100 Handle domain(THREAD, (oop)NULL);
101 if (!accessing_klass.is_null()) {
102 loader = Handle(THREAD, accessing_klass->class_loader());
103 domain = Handle(THREAD, accessing_klass->protection_domain());
104 }
105
106 KlassHandle found_klass;
107 {
108 ttyUnlocker ttyul; // release tty lock to avoid ordering problems
109 MutexLocker ml(Compile_lock);
110 Klass* kls;
111 if (!require_local) {
112 kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_(KlassHandle()));
113 } else {
114 kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_(KlassHandle()));
115 }
116 found_klass = KlassHandle(THREAD, kls);
117 }
118
119 // If we fail to find an array klass, look again for its element type.
120 // The element type may be available either locally or via constraints.
121 // In either case, if we can find the element type in the system dictionary,
122 // we must build an array type around it. The CI requires array klasses
123 // to be loaded if their element klasses are loaded, except when memory
124 // is exhausted.
125 if (sym->byte_at(0) == '[' &&
126 (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
127 // We have an unloaded array.
128 // Build it on the fly if the element class exists.
129 TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
130 sym->utf8_length()-1,
131 CHECK_(KlassHandle()));
132
133 // Get element Klass recursively.
134 KlassHandle elem_klass =
135 get_klass_by_name_impl(accessing_klass,
136 cpool,
137 elem_sym,
138 require_local);
139 if (!elem_klass.is_null()) {
140 // Now make an array for it
141 return elem_klass->array_klass(CHECK_(KlassHandle()));
142 }
143 }
144
145 if (found_klass.is_null() && !cpool.is_null() && cpool->has_preresolution()) {
146 // Look inside the constant pool for pre-resolved class entries.
147 for (int i = cpool->length() - 1; i >= 1; i--) {
148 if (cpool->tag_at(i).is_klass()) {
149 Klass* kls = cpool->resolved_klass_at(i);
150 if (kls->name() == sym) {
151 return kls;
152 }
153 }
154 }
155 }
156
157 return found_klass();
158 }
159
160 // ------------------------------------------------------------------
161 KlassHandle JVMCIEnv::get_klass_by_name(KlassHandle& accessing_klass,
162 Symbol* klass_name,
163 bool require_local) {
164 ResourceMark rm;
165 constantPoolHandle cpool;
166 return get_klass_by_name_impl(accessing_klass,
167 cpool,
168 klass_name,
169 require_local);
170 }
171
172 // ------------------------------------------------------------------
173 // Implementation of get_klass_by_index.
174 KlassHandle JVMCIEnv::get_klass_by_index_impl(constantPoolHandle& cpool,
175 int index,
176 bool& is_accessible,
177 KlassHandle& accessor) {
178 JVMCI_EXCEPTION_CONTEXT;
179 KlassHandle klass (THREAD, ConstantPool::klass_at_if_loaded(cpool, index));
180 Symbol* klass_name = NULL;
181 if (klass.is_null()) {
182 // The klass has not been inserted into the constant pool.
183 // Try to look it up by name.
184 {
185 // We have to lock the cpool to keep the oop from being resolved
186 // while we are accessing it.
187 MonitorLockerEx ml(cpool->lock());
188
189 constantTag tag = cpool->tag_at(index);
190 if (tag.is_klass()) {
191 // The klass has been inserted into the constant pool
192 // very recently.
193 klass = KlassHandle(THREAD, cpool->resolved_klass_at(index));
194 } else if (tag.is_symbol()) {
195 klass_name = cpool->symbol_at(index);
196 } else {
197 assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag");
198 klass_name = cpool->unresolved_klass_at(index);
199 }
200 }
201 }
202
203 if (klass.is_null()) {
204 // Not found in constant pool. Use the name to do the lookup.
205 KlassHandle k = get_klass_by_name_impl(accessor,
206 cpool,
207 klass_name,
208 false);
209 // Calculate accessibility the hard way.
210 if (k.is_null()) {
211 is_accessible = false;
212 } else if (k->class_loader() != accessor->class_loader() &&
213 get_klass_by_name_impl(accessor, cpool, k->name(), true).is_null()) {
214 // Loaded only remotely. Not linked yet.
215 is_accessible = false;
216 } else {
217 // Linked locally, and we must also check public/private, etc.
218 is_accessible = check_klass_accessibility(accessor, k);
219 }
220 if (!is_accessible) {
221 return KlassHandle();
222 }
223 return k;
224 }
225
226 // It is known to be accessible, since it was found in the constant pool.
227 is_accessible = true;
228 return klass;
229 }
230
231 // ------------------------------------------------------------------
232 // Get a klass from the constant pool.
233 KlassHandle JVMCIEnv::get_klass_by_index(constantPoolHandle& cpool,
234 int index,
235 bool& is_accessible,
236 KlassHandle& accessor) {
237 ResourceMark rm;
238 KlassHandle result = get_klass_by_index_impl(cpool, index, is_accessible, accessor);
239 return result;
240 }
241
242 // ------------------------------------------------------------------
243 // Implementation of get_field_by_index.
244 //
245 // Implementation note: the results of field lookups are cached
246 // in the accessor klass.
247 void JVMCIEnv::get_field_by_index_impl(instanceKlassHandle& klass, fieldDescriptor& field_desc,
248 int index) {
249 JVMCI_EXCEPTION_CONTEXT;
250
251 assert(klass->is_linked(), "must be linked before using its constant-pool");
252
253 constantPoolHandle cpool(thread, klass->constants());
254
255 // Get the field's name, signature, and type.
256 Symbol* name = cpool->name_ref_at(index);
257
258 int nt_index = cpool->name_and_type_ref_index_at(index);
259 int sig_index = cpool->signature_ref_index_at(nt_index);
260 Symbol* signature = cpool->symbol_at(sig_index);
261
262 // Get the field's declared holder.
263 int holder_index = cpool->klass_ref_index_at(index);
264 bool holder_is_accessible;
265 KlassHandle declared_holder = get_klass_by_index(cpool, holder_index,
266 holder_is_accessible,
267 klass);
268
269 // The declared holder of this field may not have been loaded.
270 // Bail out with partial field information.
271 if (!holder_is_accessible) {
272 return;
273 }
274
275
276 // Perform the field lookup.
277 Klass* canonical_holder =
278 InstanceKlass::cast(declared_holder())->find_field(name, signature, &field_desc);
279 if (canonical_holder == NULL) {
280 return;
281 }
282
283 assert(canonical_holder == field_desc.field_holder(), "just checking");
284 }
285
286 // ------------------------------------------------------------------
287 // Get a field by index from a klass's constant pool.
288 void JVMCIEnv::get_field_by_index(instanceKlassHandle& accessor, fieldDescriptor& fd, int index) {
289 ResourceMark rm;
290 return get_field_by_index_impl(accessor, fd, index);
291 }
292
293 // ------------------------------------------------------------------
294 // Perform an appropriate method lookup based on accessor, holder,
295 // name, signature, and bytecode.
296 methodHandle JVMCIEnv::lookup_method(instanceKlassHandle& h_accessor,
297 instanceKlassHandle& h_holder,
298 Symbol* name,
299 Symbol* sig,
300 Bytecodes::Code bc) {
301 JVMCI_EXCEPTION_CONTEXT;
302 LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
303 methodHandle dest_method;
304 switch (bc) {
305 case Bytecodes::_invokestatic:
306 dest_method =
307 LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
308 break;
309 case Bytecodes::_invokespecial:
310 dest_method =
311 LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
312 break;
313 case Bytecodes::_invokeinterface:
314 dest_method =
315 LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
316 h_accessor, true);
317 break;
318 case Bytecodes::_invokevirtual:
319 dest_method =
320 LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
321 h_accessor, true);
322 break;
323 default: ShouldNotReachHere();
324 }
325
326 return dest_method;
327 }
328
329
330 // ------------------------------------------------------------------
331 methodHandle JVMCIEnv::get_method_by_index_impl(constantPoolHandle& cpool,
332 int index, Bytecodes::Code bc,
333 instanceKlassHandle& accessor) {
334 if (bc == Bytecodes::_invokedynamic) {
335 ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
336 bool is_resolved = !cpce->is_f1_null();
337 if (is_resolved) {
338 // Get the invoker Method* from the constant pool.
339 // (The appendix argument, if any, will be noted in the method's signature.)
340 Method* adapter = cpce->f1_as_method();
341 return methodHandle(adapter);
342 }
343
344 return NULL;
345 }
346
347 int holder_index = cpool->klass_ref_index_at(index);
348 bool holder_is_accessible;
349 KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
350
351 // Get the method's name and signature.
352 Symbol* name_sym = cpool->name_ref_at(index);
353 Symbol* sig_sym = cpool->signature_ref_at(index);
354
355 if (cpool->has_preresolution()
356 || (holder() == SystemDictionary::MethodHandle_klass() &&
357 MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) {
358 // Short-circuit lookups for JSR 292-related call sites.
359 // That is, do not rely only on name-based lookups, because they may fail
360 // if the names are not resolvable in the boot class loader (7056328).
361 switch (bc) {
362 case Bytecodes::_invokevirtual:
363 case Bytecodes::_invokeinterface:
364 case Bytecodes::_invokespecial:
365 case Bytecodes::_invokestatic:
366 {
367 Method* m = ConstantPool::method_at_if_loaded(cpool, index);
368 if (m != NULL) {
369 return m;
370 }
371 }
372 break;
373 }
374 }
375
376 if (holder_is_accessible) { // Our declared holder is loaded.
377 instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
378 methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
379 if (!m.is_null() &&
380 (bc == Bytecodes::_invokestatic
381 ? InstanceKlass::cast(m->method_holder())->is_not_initialized()
382 : !InstanceKlass::cast(m->method_holder())->is_loaded())) {
383 m = NULL;
384 }
385 if (!m.is_null()) {
386 // We found the method.
387 return m;
388 }
389 }
390
391 // Either the declared holder was not loaded, or the method could
392 // not be found.
393
394 return NULL;
395 }
396
397 // ------------------------------------------------------------------
398 instanceKlassHandle JVMCIEnv::get_instance_klass_for_declared_method_holder(KlassHandle& method_holder) {
399 // For the case of <array>.clone(), the method holder can be an ArrayKlass*
400 // instead of an InstanceKlass*. For that case simply pretend that the
401 // declared holder is Object.clone since that's where the call will bottom out.
402 if (method_holder->oop_is_instance()) {
403 return instanceKlassHandle(method_holder());
404 } else if (method_holder->oop_is_array()) {
405 return instanceKlassHandle(SystemDictionary::Object_klass());
406 } else {
407 ShouldNotReachHere();
408 }
409 return NULL;
410 }
411
412
413 // ------------------------------------------------------------------
414 methodHandle JVMCIEnv::get_method_by_index(constantPoolHandle& cpool,
415 int index, Bytecodes::Code bc,
416 instanceKlassHandle& accessor) {
417 ResourceMark rm;
418 return get_method_by_index_impl(cpool, index, bc, accessor);
419 }
420
421 // ------------------------------------------------------------------
422 // Check for changes to the system dictionary during compilation
423 // class loads, evolution, breakpoints
424 JVMCIEnv::CodeInstallResult JVMCIEnv::check_for_system_dictionary_modification(Dependencies* dependencies, Handle compiled_code,
425 JVMCIEnv* env, char** failure_detail) {
426 // If JVMTI capabilities were enabled during compile, the compilation is invalidated.
427 if (env != NULL) {
428 if (!env->_jvmti_can_hotswap_or_post_breakpoint && JvmtiExport::can_hotswap_or_post_breakpoint()) {
429 *failure_detail = (char*) "Hotswapping or breakpointing was enabled during compilation";
430 return JVMCIEnv::dependencies_failed;
431 }
432 }
433
434 // Dependencies must be checked when the system dictionary changes
435 // or if we don't know whether it has changed (i.e., env == NULL).
436 // In debug mode, always check dependencies.
437 bool counter_changed = env != NULL && env->_system_dictionary_modification_counter != SystemDictionary::number_of_modifications();
438 bool verify_deps = env == NULL || trueInDebug || Debug::ENABLED();
439 if (!counter_changed && !verify_deps) {
440 return JVMCIEnv::ok;
441 }
442
443 for (Dependencies::DepStream deps(dependencies); deps.next(); ) {
444 Klass* witness = deps.check_dependency();
445 if (witness != NULL) {
446 // Use a fixed size buffer to prevent the string stream from
447 // resizing in the context of an inner resource mark.
448 char* buffer = NEW_RESOURCE_ARRAY(char, O_BUFLEN);
449 stringStream st(buffer, O_BUFLEN);
450 deps.print_dependency(witness, true, &st);
451 *failure_detail = st.as_string();
452 if (env == NULL || counter_changed) {
453 return JVMCIEnv::dependencies_failed;
454 } else {
455 // The dependencies were invalid at the time of installation
456 // without any intervening modification of the system
457 // dictionary. That means they were invalidly constructed.
458 return JVMCIEnv::dependencies_invalid;
459 }
460 }
461 if (LogCompilation) {
462 deps.log_dependency();
463 }
464 }
465
466 return JVMCIEnv::ok;
467 }
468
469 // ------------------------------------------------------------------
470 JVMCIEnv::CodeInstallResult JVMCIEnv::register_method(
471 methodHandle& method,
472 nmethod*& nm,
473 int entry_bci,
474 CodeOffsets* offsets,
475 int orig_pc_offset,
476 CodeBuffer* code_buffer,
477 int frame_words,
478 OopMapSet* oop_map_set,
479 ExceptionHandlerTable* handler_table,
480 AbstractCompiler* compiler,
481 DebugInformationRecorder* debug_info,
482 Dependencies* dependencies,
483 JVMCIEnv* env,
484 int compile_id,
485 bool has_unsafe_access,
486 Handle installed_code,
487 Handle compiled_code,
488 Handle speculation_log) {
489 JVMCI_EXCEPTION_CONTEXT;
490 NMethodSweeper::possibly_sweep();
491 nm = NULL;
492 int comp_level = CompLevel_full_optimization;
493 char* failure_detail = NULL;
494 JVMCIEnv::CodeInstallResult result;
495 {
496 // To prevent compile queue updates.
497 MutexLocker locker(MethodCompileQueue_lock, THREAD);
498
499 // Prevent SystemDictionary::add_to_hierarchy from running
500 // and invalidating our dependencies until we install this method.
501 MutexLocker ml(Compile_lock);
502
503 // Encode the dependencies now, so we can check them right away.
504 dependencies->encode_content_bytes();
505
506 // Check for {class loads, evolution, breakpoints} during compilation
507 result = check_for_system_dictionary_modification(dependencies, compiled_code, env, &failure_detail);
508 if (result != JVMCIEnv::ok) {
509 // While not a true deoptimization, it is a preemptive decompile.
510 MethodData* mdp = method()->method_data();
511 if (mdp != NULL) {
512 mdp->inc_decompile_count();
513 if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
514 // TODO (chaeubl) enable this in the fastdebug build only once we are more stable
515 ResourceMark m;
516 tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
517 //ShouldNotReachHere();
518 }
519 }
520
521 // All buffers in the CodeBuffer are allocated in the CodeCache.
522 // If the code buffer is created on each compile attempt
523 // as in C2, then it must be freed.
524 //code_buffer->free_blob();
525 } else {
526 ImplicitExceptionTable implicit_tbl;
527 nm = nmethod::new_nmethod(method,
528 compile_id,
529 entry_bci,
530 offsets,
531 orig_pc_offset,
532 debug_info, dependencies, code_buffer,
533 frame_words, oop_map_set,
534 handler_table, &implicit_tbl,
535 compiler, comp_level, installed_code, speculation_log);
536
537 // Free codeBlobs
538 //code_buffer->free_blob();
539
540 if (nm == NULL) {
541 // The CodeCache is full. Print out warning and disable compilation.
542 {
543 MutexUnlocker ml(Compile_lock);
544 MutexUnlocker locker(MethodCompileQueue_lock);
545 CompileBroker::handle_full_code_cache();
546 }
547 } else {
548 nm->set_has_unsafe_access(has_unsafe_access);
549 #ifdef TARGET_ARCH_x86
550 // It might be preferable to set this only for methods which
551 // use vector instructions but we currently don't track this
552 // and it probably wouldn't make much difference.
553 nm->set_has_wide_vectors(MaxVectorSize > 16);
554 #endif
555
556 // Record successful registration.
557 // (Put nm into the task handle *before* publishing to the Java heap.)
558 CompileTask* task = env == NULL ? NULL : env->task();
559 if (task != NULL) task->set_code(nm);
560
561 if (installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(installed_code())) {
562 if (entry_bci == InvocationEntryBci) {
563 if (TieredCompilation) {
564 // If there is an old version we're done with it
565 nmethod* old = method->code();
566 if (TraceMethodReplacement && old != NULL) {
567 ResourceMark rm;
568 char *method_name = method->name_and_sig_as_C_string();
569 tty->print_cr("Replacing method %s", method_name);
570 }
571 if (old != NULL ) {
572 old->make_not_entrant();
573 }
574 }
575 if (TraceNMethodInstalls) {
576 ResourceMark rm;
577 char *method_name = method->name_and_sig_as_C_string();
578 ttyLocker ttyl;
579 tty->print_cr("Installing method (%d) %s [entry point: %p]",
580 comp_level,
581 method_name, nm->entry_point());
582 }
583 // Allow the code to be executed
584 method->set_code(method, nm);
585 } else {
586 if (TraceNMethodInstalls ) {
587 ResourceMark rm;
588 char *method_name = method->name_and_sig_as_C_string();
589 ttyLocker ttyl;
590 tty->print_cr("Installing osr method (%d) %s @ %d",
591 comp_level,
592 method_name,
593 entry_bci);
594 }
595 InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
596 }
597 }
598 }
599 result = nm != NULL ? JVMCIEnv::ok :JVMCIEnv::cache_full;
600 }
601 }
602
603 // String creation must be done outside lock
604 if (failure_detail != NULL) {
605 // A failure to allocate the string is silently ignored.
606 Handle message = java_lang_String::create_from_str(failure_detail, THREAD);
607 HotSpotCompiledNmethod::set_installationFailureMessage(compiled_code, message());
608 }
609
610 // JVMTI -- compiled method notification (must be done outside lock)
611 if (nm != NULL) {
612 nm->post_compiled_method_load_event();
613 }
614
615 return result;
616 }
617