29 #include "compiler/compileLog.hpp"
30 #include "oops/objArrayKlass.hpp"
31 #include "opto/addnode.hpp"
32 #include "opto/callGenerator.hpp"
33 #include "opto/cfgnode.hpp"
34 #include "opto/idealKit.hpp"
35 #include "opto/mulnode.hpp"
36 #include "opto/parse.hpp"
37 #include "opto/runtime.hpp"
38 #include "opto/subnode.hpp"
39 #include "prims/nativeLookup.hpp"
40 #include "runtime/sharedRuntime.hpp"
41 #include "trace/traceMacros.hpp"
42
43 class LibraryIntrinsic : public InlineCallGenerator {
44 // Extend the set of intrinsics known to the runtime:
45 public:
46 private:
47 bool _is_virtual;
48 bool _is_predicted;
49 vmIntrinsics::ID _intrinsic_id;
50
51 public:
52 LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, vmIntrinsics::ID id)
53 : InlineCallGenerator(m),
54 _is_virtual(is_virtual),
55 _is_predicted(is_predicted),
56 _intrinsic_id(id)
57 {
58 }
59 virtual bool is_intrinsic() const { return true; }
60 virtual bool is_virtual() const { return _is_virtual; }
61 virtual bool is_predicted() const { return _is_predicted; }
62 virtual JVMState* generate(JVMState* jvms);
63 virtual Node* generate_predicate(JVMState* jvms);
64 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
65 };
66
67
68 // Local helper class for LibraryIntrinsic:
69 class LibraryCallKit : public GraphKit {
70 private:
71 LibraryIntrinsic* _intrinsic; // the library intrinsic being called
72 Node* _result; // the result node, if any
73 int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted
74
75 const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false);
76
77 public:
78 LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic)
79 : GraphKit(jvms),
80 _intrinsic(intrinsic),
81 _result(NULL)
335 case vmIntrinsics::_compareTo:
336 case vmIntrinsics::_equals:
337 case vmIntrinsics::_equalsC:
338 case vmIntrinsics::_getAndAddInt:
339 case vmIntrinsics::_getAndAddLong:
340 case vmIntrinsics::_getAndSetInt:
341 case vmIntrinsics::_getAndSetLong:
342 case vmIntrinsics::_getAndSetObject:
343 case vmIntrinsics::_loadFence:
344 case vmIntrinsics::_storeFence:
345 case vmIntrinsics::_fullFence:
346 break; // InlineNatives does not control String.compareTo
347 case vmIntrinsics::_Reference_get:
348 break; // InlineNatives does not control Reference.get
349 default:
350 return NULL;
351 }
352 }
353
354 bool is_predicted = false;
355
356 switch (id) {
357 case vmIntrinsics::_compareTo:
358 if (!SpecialStringCompareTo) return NULL;
359 if (!Matcher::match_rule_supported(Op_StrComp)) return NULL;
360 break;
361 case vmIntrinsics::_indexOf:
362 if (!SpecialStringIndexOf) return NULL;
363 break;
364 case vmIntrinsics::_equals:
365 if (!SpecialStringEquals) return NULL;
366 if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL;
367 break;
368 case vmIntrinsics::_equalsC:
369 if (!SpecialArraysEquals) return NULL;
370 if (!Matcher::match_rule_supported(Op_AryEq)) return NULL;
371 break;
372 case vmIntrinsics::_arraycopy:
373 if (!InlineArrayCopy) return NULL;
374 break;
375 case vmIntrinsics::_copyMemory:
376 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL;
377 if (!InlineArrayCopy) return NULL;
378 break;
379 case vmIntrinsics::_hashCode:
380 if (!InlineObjectHash) return NULL;
381 break;
382 case vmIntrinsics::_clone:
383 case vmIntrinsics::_copyOf:
384 case vmIntrinsics::_copyOfRange:
385 if (!InlineObjectCopy) return NULL;
386 // These also use the arraycopy intrinsic mechanism:
387 if (!InlineArrayCopy) return NULL;
388 break;
389 case vmIntrinsics::_encodeISOArray:
390 if (!SpecialEncodeISOArray) return NULL;
391 if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL;
392 break;
393 case vmIntrinsics::_checkIndex:
394 // We do not intrinsify this. The optimizer does fine with it.
395 return NULL;
396
397 case vmIntrinsics::_getCallerClass:
398 if (!UseNewReflection) return NULL;
399 if (!InlineReflectionGetCallerClass) return NULL;
400 if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL;
401 break;
402
512 if (!InlineClassNatives) return NULL;
513 }
514
515 // -XX:-InlineThreadNatives disables natives from the Thread class.
516 if (m->holder()->name() == ciSymbol::java_lang_Thread()) {
517 if (!InlineThreadNatives) return NULL;
518 }
519
520 // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes.
521 if (m->holder()->name() == ciSymbol::java_lang_Math() ||
522 m->holder()->name() == ciSymbol::java_lang_Float() ||
523 m->holder()->name() == ciSymbol::java_lang_Double()) {
524 if (!InlineMathNatives) return NULL;
525 }
526
527 // -XX:-InlineUnsafeOps disables natives from the Unsafe class.
528 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) {
529 if (!InlineUnsafeOps) return NULL;
530 }
531
532 return new LibraryIntrinsic(m, is_virtual, is_predicted, (vmIntrinsics::ID) id);
533 }
534
535 //----------------------register_library_intrinsics-----------------------
536 // Initialize this file's data structures, for each Compile instance.
537 void Compile::register_library_intrinsics() {
538 // Nothing to do here.
539 }
540
541 JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
542 LibraryCallKit kit(jvms, this);
543 Compile* C = kit.C;
544 int nodes = C->unique();
545 #ifndef PRODUCT
546 if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) {
547 char buf[1000];
548 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
549 tty->print_cr("Intrinsic %s", str);
550 }
551 #endif
552 ciMethod* callee = kit.callee();
|
29 #include "compiler/compileLog.hpp"
30 #include "oops/objArrayKlass.hpp"
31 #include "opto/addnode.hpp"
32 #include "opto/callGenerator.hpp"
33 #include "opto/cfgnode.hpp"
34 #include "opto/idealKit.hpp"
35 #include "opto/mulnode.hpp"
36 #include "opto/parse.hpp"
37 #include "opto/runtime.hpp"
38 #include "opto/subnode.hpp"
39 #include "prims/nativeLookup.hpp"
40 #include "runtime/sharedRuntime.hpp"
41 #include "trace/traceMacros.hpp"
42
43 class LibraryIntrinsic : public InlineCallGenerator {
44 // Extend the set of intrinsics known to the runtime:
45 public:
46 private:
47 bool _is_virtual;
48 bool _is_predicted;
49 bool _does_virtual_dispatch;
50 vmIntrinsics::ID _intrinsic_id;
51
52 public:
53 LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id)
54 : InlineCallGenerator(m),
55 _is_virtual(is_virtual),
56 _is_predicted(is_predicted),
57 _does_virtual_dispatch(does_virtual_dispatch),
58 _intrinsic_id(id)
59 {
60 }
61 virtual bool is_intrinsic() const { return true; }
62 virtual bool is_virtual() const { return _is_virtual; }
63 virtual bool is_predicted() const { return _is_predicted; }
64 virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; }
65 virtual JVMState* generate(JVMState* jvms);
66 virtual Node* generate_predicate(JVMState* jvms);
67 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
68 };
69
70
71 // Local helper class for LibraryIntrinsic:
72 class LibraryCallKit : public GraphKit {
73 private:
74 LibraryIntrinsic* _intrinsic; // the library intrinsic being called
75 Node* _result; // the result node, if any
76 int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted
77
78 const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false);
79
80 public:
81 LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic)
82 : GraphKit(jvms),
83 _intrinsic(intrinsic),
84 _result(NULL)
338 case vmIntrinsics::_compareTo:
339 case vmIntrinsics::_equals:
340 case vmIntrinsics::_equalsC:
341 case vmIntrinsics::_getAndAddInt:
342 case vmIntrinsics::_getAndAddLong:
343 case vmIntrinsics::_getAndSetInt:
344 case vmIntrinsics::_getAndSetLong:
345 case vmIntrinsics::_getAndSetObject:
346 case vmIntrinsics::_loadFence:
347 case vmIntrinsics::_storeFence:
348 case vmIntrinsics::_fullFence:
349 break; // InlineNatives does not control String.compareTo
350 case vmIntrinsics::_Reference_get:
351 break; // InlineNatives does not control Reference.get
352 default:
353 return NULL;
354 }
355 }
356
357 bool is_predicted = false;
358 bool does_virtual_dispatch = false;
359
360 switch (id) {
361 case vmIntrinsics::_compareTo:
362 if (!SpecialStringCompareTo) return NULL;
363 if (!Matcher::match_rule_supported(Op_StrComp)) return NULL;
364 break;
365 case vmIntrinsics::_indexOf:
366 if (!SpecialStringIndexOf) return NULL;
367 break;
368 case vmIntrinsics::_equals:
369 if (!SpecialStringEquals) return NULL;
370 if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL;
371 break;
372 case vmIntrinsics::_equalsC:
373 if (!SpecialArraysEquals) return NULL;
374 if (!Matcher::match_rule_supported(Op_AryEq)) return NULL;
375 break;
376 case vmIntrinsics::_arraycopy:
377 if (!InlineArrayCopy) return NULL;
378 break;
379 case vmIntrinsics::_copyMemory:
380 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL;
381 if (!InlineArrayCopy) return NULL;
382 break;
383 case vmIntrinsics::_hashCode:
384 if (!InlineObjectHash) return NULL;
385 does_virtual_dispatch = true;
386 break;
387 case vmIntrinsics::_clone:
388 does_virtual_dispatch = true;
389 case vmIntrinsics::_copyOf:
390 case vmIntrinsics::_copyOfRange:
391 if (!InlineObjectCopy) return NULL;
392 // These also use the arraycopy intrinsic mechanism:
393 if (!InlineArrayCopy) return NULL;
394 break;
395 case vmIntrinsics::_encodeISOArray:
396 if (!SpecialEncodeISOArray) return NULL;
397 if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL;
398 break;
399 case vmIntrinsics::_checkIndex:
400 // We do not intrinsify this. The optimizer does fine with it.
401 return NULL;
402
403 case vmIntrinsics::_getCallerClass:
404 if (!UseNewReflection) return NULL;
405 if (!InlineReflectionGetCallerClass) return NULL;
406 if (SystemDictionary::reflect_CallerSensitive_klass() == NULL) return NULL;
407 break;
408
518 if (!InlineClassNatives) return NULL;
519 }
520
521 // -XX:-InlineThreadNatives disables natives from the Thread class.
522 if (m->holder()->name() == ciSymbol::java_lang_Thread()) {
523 if (!InlineThreadNatives) return NULL;
524 }
525
526 // -XX:-InlineMathNatives disables natives from the Math,Float and Double classes.
527 if (m->holder()->name() == ciSymbol::java_lang_Math() ||
528 m->holder()->name() == ciSymbol::java_lang_Float() ||
529 m->holder()->name() == ciSymbol::java_lang_Double()) {
530 if (!InlineMathNatives) return NULL;
531 }
532
533 // -XX:-InlineUnsafeOps disables natives from the Unsafe class.
534 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) {
535 if (!InlineUnsafeOps) return NULL;
536 }
537
538 return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id);
539 }
540
541 //----------------------register_library_intrinsics-----------------------
542 // Initialize this file's data structures, for each Compile instance.
543 void Compile::register_library_intrinsics() {
544 // Nothing to do here.
545 }
546
547 JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
548 LibraryCallKit kit(jvms, this);
549 Compile* C = kit.C;
550 int nodes = C->unique();
551 #ifndef PRODUCT
552 if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) {
553 char buf[1000];
554 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
555 tty->print_cr("Intrinsic %s", str);
556 }
557 #endif
558 ciMethod* callee = kit.callee();
|