< prev index next >

src/share/vm/opto/library_call.cpp

Print this page




 205     return generate_method_call(method_id, true, false);
 206   }
 207   Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 208   Node * field_address_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 209 
 210   Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae);
 211   bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae);
 212   bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae);
 213   bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae);
 214   Node* make_indexOf_node(Node* src_start, Node* src_count, Node* tgt_start, Node* tgt_count,
 215                           RegionNode* region, Node* phi, StrIntrinsicNode::ArgEnc ae);
 216   bool inline_string_indexOfChar();
 217   bool inline_string_equals(StrIntrinsicNode::ArgEnc ae);
 218   bool inline_string_toBytesU();
 219   bool inline_string_getCharsU();
 220   bool inline_string_copy(bool compress);
 221   bool inline_string_char_access(bool is_store);
 222   Node* round_double_node(Node* n);
 223   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
 224   bool inline_math_native(vmIntrinsics::ID id);
 225   bool inline_trig(vmIntrinsics::ID id);
 226   bool inline_math(vmIntrinsics::ID id);
 227   template <typename OverflowOp>
 228   bool inline_math_overflow(Node* arg1, Node* arg2);
 229   void inline_math_mathExact(Node* math, Node* test);
 230   bool inline_math_addExactI(bool is_increment);
 231   bool inline_math_addExactL(bool is_increment);
 232   bool inline_math_multiplyExactI();
 233   bool inline_math_multiplyExactL();
 234   bool inline_math_negateExactI();
 235   bool inline_math_negateExactL();
 236   bool inline_math_subtractExactI(bool is_decrement);
 237   bool inline_math_subtractExactL(bool is_decrement);
 238   bool inline_min_max(vmIntrinsics::ID id);
 239   bool inline_notify(vmIntrinsics::ID id);
 240   Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y);
 241   // This returns Type::AnyPtr, RawPtr, or OopPtr.
 242   int classify_unsafe_addr(Node* &base, Node* &offset);
 243   Node* make_unsafe_address(Node* base, Node* offset);
 244   // Helper for inline_unsafe_access.
 245   // Generates the guards that check whether the result of


1671 Node* LibraryCallKit::round_double_node(Node* n) {
1672   if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1)
1673     n = _gvn.transform(new RoundDoubleNode(0, n));
1674   return n;
1675 }
1676 
1677 //------------------------------inline_math-----------------------------------
1678 // public static double Math.abs(double)
1679 // public static double Math.sqrt(double)
1680 // public static double Math.log(double)
1681 // public static double Math.log10(double)
1682 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) {
1683   Node* arg = round_double_node(argument(0));
1684   Node* n = NULL;
1685   switch (id) {
1686   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1687   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1688   default:  fatal_unexpected_iid(id);  break;
1689   }
1690   set_result(_gvn.transform(n));
1691   return true;
1692 }
1693 
1694 //------------------------------inline_trig----------------------------------
1695 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
1696 // argument reduction which will turn into a fast/slow diamond.
1697 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1698   Node* arg = round_double_node(argument(0));
1699   Node* n = NULL;
1700 
1701   n = _gvn.transform(n);
1702 
1703   // Rounding required?  Check for argument reduction!
1704   if (Matcher::strict_fp_requires_explicit_rounding) {
1705     static const double     pi_4 =  0.7853981633974483;
1706     static const double neg_pi_4 = -0.7853981633974483;
1707     // pi/2 in 80-bit extended precision
1708     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
1709     // -pi/2 in 80-bit extended precision
1710     // static const unsigned char neg_pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x00};
1711     // Cutoff value for using this argument reduction technique
1712     //static const double    pi_2_minus_epsilon =  1.564660403643354;
1713     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
1714 
1715     // Pseudocode for sin:
1716     // if (x <= Math.PI / 4.0) {
1717     //   if (x >= -Math.PI / 4.0) return  fsin(x);
1718     //   if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0);
1719     // } else {
1720     //   if (x <=  Math.PI / 2.0) return  fcos(x - Math.PI / 2.0);
1721     // }
1722     // return StrictMath.sin(x);
1723 
1724     // Pseudocode for cos:
1725     // if (x <= Math.PI / 4.0) {
1726     //   if (x >= -Math.PI / 4.0) return  fcos(x);
1727     //   if (x >= -Math.PI / 2.0) return  fsin(x + Math.PI / 2.0);
1728     // } else {
1729     //   if (x <=  Math.PI / 2.0) return -fsin(x - Math.PI / 2.0);
1730     // }
1731     // return StrictMath.cos(x);
1732 
1733     // Actually, sticking in an 80-bit Intel value into C2 will be tough; it
1734     // requires a special machine instruction to load it.  Instead we'll try
1735     // the 'easy' case.  If we really need the extra range +/- PI/2 we'll
1736     // probably do the math inside the SIN encoding.
1737 
1738     // Make the merge point
1739     RegionNode* r = new RegionNode(3);
1740     Node* phi = new PhiNode(r, Type::DOUBLE);
1741 
1742     // Flatten arg so we need only 1 test
1743     Node *abs = _gvn.transform(new AbsDNode(arg));
1744     // Node for PI/4 constant
1745     Node *pi4 = makecon(TypeD::make(pi_4));
1746     // Check PI/4 : abs(arg)
1747     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
1748     // Check: If PI/4 < abs(arg) then go slow
1749     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
1750     // Branch either way
1751     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
1752     set_control(opt_iff(r,iff));
1753 
1754     // Set fast path result
1755     phi->init_req(2, n);
1756 
1757     // Slow path - non-blocking leaf call
1758     Node* call = NULL;
1759     switch (id) {
1760     case vmIntrinsics::_dtan:
1761       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1762                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
1763                                "Tan", NULL, arg, top());
1764       break;
1765     }
1766     assert(control()->in(0) == call, "");
1767     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
1768     r->init_req(1, control());
1769     phi->init_req(1, slow_result);
1770 
1771     // Post-merge
1772     set_control(_gvn.transform(r));
1773     record_for_igvn(r);
1774     n = _gvn.transform(phi);
1775 
1776     C->set_has_split_ifs(true); // Has chance for split-if optimization
1777   }
1778   set_result(n);
1779   return true;
1780 }
1781 
1782 //------------------------------runtime_math-----------------------------
1783 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) {
1784   assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(),
1785          "must be (DD)D or (D)D type");
1786 
1787   // Inputs
1788   Node* a = round_double_node(argument(0));
1789   Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? round_double_node(argument(2)) : NULL;
1790 
1791   const TypePtr* no_memory_effects = NULL;
1792   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1793                                  no_memory_effects,
1794                                  a, top(), b, b ? top() : NULL);
1795   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1796 #ifdef ASSERT
1797   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1798   assert(value_top == top(), "second value must be top");




 205     return generate_method_call(method_id, true, false);
 206   }
 207   Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 208   Node * field_address_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 209 
 210   Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae);
 211   bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae);
 212   bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae);
 213   bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae);
 214   Node* make_indexOf_node(Node* src_start, Node* src_count, Node* tgt_start, Node* tgt_count,
 215                           RegionNode* region, Node* phi, StrIntrinsicNode::ArgEnc ae);
 216   bool inline_string_indexOfChar();
 217   bool inline_string_equals(StrIntrinsicNode::ArgEnc ae);
 218   bool inline_string_toBytesU();
 219   bool inline_string_getCharsU();
 220   bool inline_string_copy(bool compress);
 221   bool inline_string_char_access(bool is_store);
 222   Node* round_double_node(Node* n);
 223   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
 224   bool inline_math_native(vmIntrinsics::ID id);

 225   bool inline_math(vmIntrinsics::ID id);
 226   template <typename OverflowOp>
 227   bool inline_math_overflow(Node* arg1, Node* arg2);
 228   void inline_math_mathExact(Node* math, Node* test);
 229   bool inline_math_addExactI(bool is_increment);
 230   bool inline_math_addExactL(bool is_increment);
 231   bool inline_math_multiplyExactI();
 232   bool inline_math_multiplyExactL();
 233   bool inline_math_negateExactI();
 234   bool inline_math_negateExactL();
 235   bool inline_math_subtractExactI(bool is_decrement);
 236   bool inline_math_subtractExactL(bool is_decrement);
 237   bool inline_min_max(vmIntrinsics::ID id);
 238   bool inline_notify(vmIntrinsics::ID id);
 239   Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y);
 240   // This returns Type::AnyPtr, RawPtr, or OopPtr.
 241   int classify_unsafe_addr(Node* &base, Node* &offset);
 242   Node* make_unsafe_address(Node* base, Node* offset);
 243   // Helper for inline_unsafe_access.
 244   // Generates the guards that check whether the result of


1670 Node* LibraryCallKit::round_double_node(Node* n) {
1671   if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1)
1672     n = _gvn.transform(new RoundDoubleNode(0, n));
1673   return n;
1674 }
1675 
1676 //------------------------------inline_math-----------------------------------
1677 // public static double Math.abs(double)
1678 // public static double Math.sqrt(double)
1679 // public static double Math.log(double)
1680 // public static double Math.log10(double)
1681 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) {
1682   Node* arg = round_double_node(argument(0));
1683   Node* n = NULL;
1684   switch (id) {
1685   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1686   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1687   default:  fatal_unexpected_iid(id);  break;
1688   }
1689   set_result(_gvn.transform(n));
























































































1690   return true;
1691 }
1692 
1693 //------------------------------runtime_math-----------------------------
1694 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) {
1695   assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(),
1696          "must be (DD)D or (D)D type");
1697 
1698   // Inputs
1699   Node* a = round_double_node(argument(0));
1700   Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? round_double_node(argument(2)) : NULL;
1701 
1702   const TypePtr* no_memory_effects = NULL;
1703   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1704                                  no_memory_effects,
1705                                  a, top(), b, b ? top() : NULL);
1706   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1707 #ifdef ASSERT
1708   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1709   assert(value_top == top(), "second value must be top");


< prev index next >