src/cpu/x86/vm/templateInterpreter_x86_64.cpp

Print this page
rev 2161 : [mq]: initial-intrinsification-changes
rev 2162 : [mq]: code-review-comments-vladimir


 740     __ load_unsigned_short(rax, field_address);
 741 
 742     __ bind(xreturn_path);
 743 
 744     // _ireturn/_areturn
 745     __ pop(rdi);
 746     __ mov(rsp, r13);
 747     __ jmp(rdi);
 748     __ ret(0);
 749 
 750     // generate a vanilla interpreter entry as the slow path
 751     __ bind(slow_path);
 752     (void) generate_normal_entry(false);
 753   } else {
 754     (void) generate_normal_entry(false);
 755   }
 756 
 757   return entry_point;
 758 }
 759 

























































































 760 // Interpreter stub for calling a native method. (asm interpreter)
 761 // This sets up a somewhat different looking stack for calling the
 762 // native method than the typical interpreter frame setup.
 763 address InterpreterGenerator::generate_native_entry(bool synchronized) {
 764   // determine code generation flags
 765   bool inc_counter  = UseCompiler || CountCompiledCalls;
 766 
 767   // rbx: methodOop
 768   // r13: sender sp
 769 
 770   address entry_point = __ pc();
 771 
 772   const Address size_of_parameters(rbx, methodOopDesc::
 773                                         size_of_parameters_offset());
 774   const Address invocation_counter(rbx, methodOopDesc::
 775                                         invocation_counter_offset() +
 776                                         InvocationCounter::counter_offset());
 777   const Address access_flags      (rbx, methodOopDesc::access_flags_offset());
 778 
 779   // get parameter size (always needed)


1446   bool synchronized = false;
1447   address entry_point = NULL;
1448 
1449   switch (kind) {
1450   case Interpreter::zerolocals             :                                                                             break;
1451   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
1452   case Interpreter::native                 : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); break;
1453   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(true);  break;
1454   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry();       break;
1455   case Interpreter::accessor               : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry();    break;
1456   case Interpreter::abstract               : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();    break;
1457   case Interpreter::method_handle          : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
1458 
1459   case Interpreter::java_lang_math_sin     : // fall thru
1460   case Interpreter::java_lang_math_cos     : // fall thru
1461   case Interpreter::java_lang_math_tan     : // fall thru
1462   case Interpreter::java_lang_math_abs     : // fall thru
1463   case Interpreter::java_lang_math_log     : // fall thru
1464   case Interpreter::java_lang_math_log10   : // fall thru
1465   case Interpreter::java_lang_math_sqrt    : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);    break;


1466   default                                  : ShouldNotReachHere();                                                       break;
1467   }
1468 
1469   if (entry_point) {
1470     return entry_point;
1471   }
1472 
1473   return ((InterpreterGenerator*) this)->
1474                                 generate_normal_entry(synchronized);
1475 }
1476 
1477 // These should never be compiled since the interpreter will prefer
1478 // the compiled version to the intrinsic version.
1479 bool AbstractInterpreter::can_be_compiled(methodHandle m) {
1480   switch (method_kind(m)) {
1481     case Interpreter::java_lang_math_sin     : // fall thru
1482     case Interpreter::java_lang_math_cos     : // fall thru
1483     case Interpreter::java_lang_math_tan     : // fall thru
1484     case Interpreter::java_lang_math_abs     : // fall thru
1485     case Interpreter::java_lang_math_log     : // fall thru




 740     __ load_unsigned_short(rax, field_address);
 741 
 742     __ bind(xreturn_path);
 743 
 744     // _ireturn/_areturn
 745     __ pop(rdi);
 746     __ mov(rsp, r13);
 747     __ jmp(rdi);
 748     __ ret(0);
 749 
 750     // generate a vanilla interpreter entry as the slow path
 751     __ bind(slow_path);
 752     (void) generate_normal_entry(false);
 753   } else {
 754     (void) generate_normal_entry(false);
 755   }
 756 
 757   return entry_point;
 758 }
 759 
 760 // Method entry for java.lang.ref.Reference.get.
 761 address InterpreterGenerator::generate_Reference_get_entry(void) {
 762 #ifndef SERIALGC
 763   // Code: _aload_0, _getfield, _areturn
 764   // parameter size = 1
 765   //
 766   // The code that gets generated by this routine is split into 2 parts:
 767   //    1. The "intrinsified" code for G1 (or any SATB based GC),
 768   //    2. The slow path - which is an expansion of the regular method entry.
 769   //
 770   // Notes:-
 771   // * In the G1 code we do not check whether we need to block for
 772   //   a safepoint. If G1 is enabled then we must execute the specialized
 773   //   code for Reference.get (except when the Reference object is null)
 774   //   so that we can log the value in the referent field with an SATB
 775   //   update buffer.
 776   //   If the code for the getfield template is modified so that the
 777   //   G1 pre-barrier code is executed when the current method is
 778   //   Reference.get() then going through the normal method entry
 779   //   will be fine.
 780   // * The G1 code can, however, check the receiver object (the instance
 781   //   of java.lang.Reference) and jump to the slow path if null. If the
 782   //   Reference object is null then we obviously cannot fetch the referent
 783   //   and so we don't need to call the G1 pre-barrier. Thus we can use the
 784   //   regular method entry code to generate the NPE.
 785   //
 786   // This code is based on generate_accessor_enty.
 787   //
 788   // rbx: methodOop
 789 
 790   // r13: senderSP must preserve for slow path, set SP to it on fast path
 791 
 792   address entry = __ pc();
 793 
 794   const int referent_offset = java_lang_ref_Reference::referent_offset;
 795   guarantee(referent_offset > 0, "referent offset not initialized");
 796 
 797   if (UseG1GC) {
 798     Label slow_path;
 799     // rbx: method
 800 
 801     // Check if local 0 != NULL
 802     // If the receiver is null then it is OK to jump to the slow path.
 803     __ movptr(rax, Address(rsp, wordSize));
 804 
 805     __ testptr(rax, rax);
 806     __ jcc(Assembler::zero, slow_path);
 807 
 808     // rax: local 0
 809     // rbx: method (but can be used as scratch now)
 810     // rdx: scratch
 811     // rdi: scratch
 812 
 813     // Generate the G1 pre-barrier code to log the value of
 814     // the referent field in an SATB buffer.
 815 
 816     // Load the value of the referent field.
 817     const Address field_address(rax, referent_offset);
 818     __ load_heap_oop(rax, field_address);
 819 
 820     // Generate the G1 pre-barrier code to log the value of
 821     // the referent field in an SATB buffer.
 822     __ g1_write_barrier_pre(noreg /* obj */,
 823                             rax /* pre_val */,
 824                             r15_thread /* thread */,
 825                             rbx /* tmp */,
 826                             true /* tosca_live */,
 827                             true /* expand_call */);
 828 
 829     // _areturn
 830     __ pop(rdi);                // get return address
 831     __ mov(rsp, r13);           // set sp to sender sp
 832     __ jmp(rdi);
 833     __ ret(0);
 834 
 835     // generate a vanilla interpreter entry as the slow path
 836     __ bind(slow_path);
 837     (void) generate_normal_entry(false);
 838 
 839     return entry;
 840   }
 841 #endif // SERIALGC
 842 
 843   // If G1 is not enabled then attempt to go through the accessor entry point
 844   // Reference.get is an accessor
 845   return generate_accessor_entry();
 846 }
 847 
 848 
 849 // Interpreter stub for calling a native method. (asm interpreter)
 850 // This sets up a somewhat different looking stack for calling the
 851 // native method than the typical interpreter frame setup.
 852 address InterpreterGenerator::generate_native_entry(bool synchronized) {
 853   // determine code generation flags
 854   bool inc_counter  = UseCompiler || CountCompiledCalls;
 855 
 856   // rbx: methodOop
 857   // r13: sender sp
 858 
 859   address entry_point = __ pc();
 860 
 861   const Address size_of_parameters(rbx, methodOopDesc::
 862                                         size_of_parameters_offset());
 863   const Address invocation_counter(rbx, methodOopDesc::
 864                                         invocation_counter_offset() +
 865                                         InvocationCounter::counter_offset());
 866   const Address access_flags      (rbx, methodOopDesc::access_flags_offset());
 867 
 868   // get parameter size (always needed)


1535   bool synchronized = false;
1536   address entry_point = NULL;
1537 
1538   switch (kind) {
1539   case Interpreter::zerolocals             :                                                                             break;
1540   case Interpreter::zerolocals_synchronized: synchronized = true;                                                        break;
1541   case Interpreter::native                 : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); break;
1542   case Interpreter::native_synchronized    : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(true);  break;
1543   case Interpreter::empty                  : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry();       break;
1544   case Interpreter::accessor               : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry();    break;
1545   case Interpreter::abstract               : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();    break;
1546   case Interpreter::method_handle          : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
1547 
1548   case Interpreter::java_lang_math_sin     : // fall thru
1549   case Interpreter::java_lang_math_cos     : // fall thru
1550   case Interpreter::java_lang_math_tan     : // fall thru
1551   case Interpreter::java_lang_math_abs     : // fall thru
1552   case Interpreter::java_lang_math_log     : // fall thru
1553   case Interpreter::java_lang_math_log10   : // fall thru
1554   case Interpreter::java_lang_math_sqrt    : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);    break;
1555   case Interpreter::java_lang_ref_reference_get
1556                                            : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
1557   default                                  : ShouldNotReachHere();                                                       break;
1558   }
1559 
1560   if (entry_point) {
1561     return entry_point;
1562   }
1563 
1564   return ((InterpreterGenerator*) this)->
1565                                 generate_normal_entry(synchronized);
1566 }
1567 
1568 // These should never be compiled since the interpreter will prefer
1569 // the compiled version to the intrinsic version.
1570 bool AbstractInterpreter::can_be_compiled(methodHandle m) {
1571   switch (method_kind(m)) {
1572     case Interpreter::java_lang_math_sin     : // fall thru
1573     case Interpreter::java_lang_math_cos     : // fall thru
1574     case Interpreter::java_lang_math_tan     : // fall thru
1575     case Interpreter::java_lang_math_abs     : // fall thru
1576     case Interpreter::java_lang_math_log     : // fall thru