119 return generate_array_guard_common(kls, region, true, false);
120 }
121 Node* generate_non_objArray_guard(Node* kls, RegionNode* region) {
122 return generate_array_guard_common(kls, region, true, true);
123 }
124 Node* generate_array_guard_common(Node* kls, RegionNode* region,
125 bool obj_array, bool not_array);
126 Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region);
127 CallJavaNode* generate_method_call(vmIntrinsics::ID method_id,
128 bool is_virtual = false, bool is_static = false);
129 CallJavaNode* generate_method_call_static(vmIntrinsics::ID method_id) {
130 return generate_method_call(method_id, false, true);
131 }
132 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
133 return generate_method_call(method_id, true, false);
134 }
135
136 bool inline_string_compareTo();
137 bool inline_string_indexOf();
138 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
139 Node* pop_math_arg();
140 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
141 bool inline_math_native(vmIntrinsics::ID id);
142 bool inline_trig(vmIntrinsics::ID id);
143 bool inline_trans(vmIntrinsics::ID id);
144 bool inline_abs(vmIntrinsics::ID id);
145 bool inline_sqrt(vmIntrinsics::ID id);
146 bool inline_pow(vmIntrinsics::ID id);
147 bool inline_exp(vmIntrinsics::ID id);
148 bool inline_min_max(vmIntrinsics::ID id);
149 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y);
150 // This returns Type::AnyPtr, RawPtr, or OopPtr.
151 int classify_unsafe_addr(Node* &base, Node* &offset);
152 Node* make_unsafe_address(Node* base, Node* offset);
153 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile);
154 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static);
155 bool inline_unsafe_allocate();
156 bool inline_unsafe_copyMemory();
157 bool inline_native_currentThread();
158 bool inline_native_time_funcs(bool isNano);
243 }
244
245 // Only a few intrinsics implement a virtual dispatch.
246 // They are expensive calls which are also frequently overridden.
247 if (is_virtual) {
248 switch (id) {
249 case vmIntrinsics::_hashCode:
250 case vmIntrinsics::_clone:
251 // OK, Object.hashCode and Object.clone intrinsics come in both flavors
252 break;
253 default:
254 return NULL;
255 }
256 }
257
258 // -XX:-InlineNatives disables nearly all intrinsics:
259 if (!InlineNatives) {
260 switch (id) {
261 case vmIntrinsics::_indexOf:
262 case vmIntrinsics::_compareTo:
263 case vmIntrinsics::_equalsC:
264 break; // InlineNatives does not control String.compareTo
265 default:
266 return NULL;
267 }
268 }
269
270 switch (id) {
271 case vmIntrinsics::_compareTo:
272 if (!SpecialStringCompareTo) return NULL;
273 break;
274 case vmIntrinsics::_indexOf:
275 if (!SpecialStringIndexOf) return NULL;
276 break;
277 case vmIntrinsics::_equalsC:
278 if (!SpecialArraysEquals) return NULL;
279 break;
280 case vmIntrinsics::_arraycopy:
281 if (!InlineArrayCopy) return NULL;
282 break;
283 case vmIntrinsics::_copyMemory:
284 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL;
285 if (!InlineArrayCopy) return NULL;
286 break;
287 case vmIntrinsics::_hashCode:
288 if (!InlineObjectHash) return NULL;
289 break;
290 case vmIntrinsics::_clone:
291 case vmIntrinsics::_copyOf:
292 case vmIntrinsics::_copyOfRange:
293 if (!InlineObjectCopy) return NULL;
294 // These also use the arraycopy intrinsic mechanism:
295 if (!InlineArrayCopy) return NULL;
296 break;
419 case vmIntrinsics::_dabs:
420 case vmIntrinsics::_datan2:
421 case vmIntrinsics::_dsqrt:
422 case vmIntrinsics::_dexp:
423 case vmIntrinsics::_dlog:
424 case vmIntrinsics::_dlog10:
425 case vmIntrinsics::_dpow:
426 return inline_math_native(intrinsic_id());
427
428 case vmIntrinsics::_min:
429 case vmIntrinsics::_max:
430 return inline_min_max(intrinsic_id());
431
432 case vmIntrinsics::_arraycopy:
433 return inline_arraycopy();
434
435 case vmIntrinsics::_compareTo:
436 return inline_string_compareTo();
437 case vmIntrinsics::_indexOf:
438 return inline_string_indexOf();
439
440 case vmIntrinsics::_getObject:
441 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false);
442 case vmIntrinsics::_getBoolean:
443 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false);
444 case vmIntrinsics::_getByte:
445 return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, false);
446 case vmIntrinsics::_getShort:
447 return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, false);
448 case vmIntrinsics::_getChar:
449 return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, false);
450 case vmIntrinsics::_getInt:
451 return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, false);
452 case vmIntrinsics::_getLong:
453 return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, false);
454 case vmIntrinsics::_getFloat:
455 return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, false);
456 case vmIntrinsics::_getDouble:
457 return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, false);
458
803 return true;
804 }
805
806 ciInstanceKlass* klass = env()->String_klass();
807 const TypeInstPtr* string_type =
808 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
809
810 Node* compare =
811 _gvn.transform(new (C, 7) StrCompNode(
812 control(),
813 memory(TypeAryPtr::CHARS),
814 memory(string_type->add_offset(value_offset)),
815 memory(string_type->add_offset(count_offset)),
816 memory(string_type->add_offset(offset_offset)),
817 receiver,
818 argument));
819 push(compare);
820 return true;
821 }
822
823 //------------------------------inline_array_equals----------------------------
824 bool LibraryCallKit::inline_array_equals() {
825
826 if (!Matcher::has_match_rule(Op_AryEq)) return false;
827
828 _sp += 2;
829 Node *argument2 = pop();
830 Node *argument1 = pop();
831
832 Node* equals =
833 _gvn.transform(new (C, 3) AryEqNode(control(),
834 argument1,
835 argument2)
836 );
837 push(equals);
838 return true;
839 }
840
841 // Java version of String.indexOf(constant string)
842 // class StringDecl {
967 }__ end_loop(); __ dead(j);
968 __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i);
969 __ goto_(return_);
970 }__ end_if();
971 __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); {
972 __ increment(i, targetCountLess1);
973 }__ end_if();
974 __ increment(i, one);
975 __ bind(outer_loop);
976 }__ end_loop(); __ dead(i);
977 __ bind(return_);
978 __ drain_delay_transform();
979
980 set_control(__ ctrl());
981 Node* result = __ value(rtn);
982 #undef __
983 C->set_has_loops(true);
984 return result;
985 }
986
987
988 //------------------------------inline_string_indexOf------------------------
989 bool LibraryCallKit::inline_string_indexOf() {
990
991 _sp += 2;
992 Node *argument = pop(); // pop non-receiver first: it was pushed second
993 Node *receiver = pop();
994
995 // don't intrinsify is argument isn't a constant string.
996 if (!argument->is_Con()) {
997 return false;
998 }
999 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr();
1000 if (str_type == NULL) {
1001 return false;
1002 }
1003 ciInstanceKlass* klass = env()->String_klass();
1004 ciObject* str_const = str_type->const_oop();
1005 if (str_const == NULL || str_const->klass() != klass) {
1006 return false;
1007 }
1024 }
1025
1026 // Null check on self without removing any arguments. The argument
1027 // null check technically happens in the wrong place, which can lead to
1028 // invalid stack traces when string compare is inlined into a method
1029 // which handles NullPointerExceptions.
1030 _sp += 2;
1031 receiver = do_null_check(receiver, T_OBJECT);
1032 // No null check on the argument is needed since it's a constant String oop.
1033 _sp -= 2;
1034 if (stopped()) {
1035 return true;
1036 }
1037
1038 // The null string as a pattern always returns 0 (match at beginning of string)
1039 if (c == 0) {
1040 push(intcon(0));
1041 return true;
1042 }
1043
1044 jchar lastChar = pat->char_at(o + (c - 1));
1045 int cache = 0;
1046 int i;
1047 for (i = 0; i < c - 1; i++) {
1048 assert(i < pat->length(), "out of range");
1049 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
1050 }
1051
1052 int md2 = c;
1053 for (i = 0; i < c - 1; i++) {
1054 assert(i < pat->length(), "out of range");
1055 if (pat->char_at(o + i) == lastChar) {
1056 md2 = (c - 1) - i;
1057 }
1058 }
1059
1060 Node* result = string_indexOf(receiver, pat, o, cache, md2);
1061 push(result);
1062 return true;
1063 }
1064
1065 //--------------------------pop_math_arg--------------------------------
1066 // Pop a double argument to a math function from the stack
1067 // rounding it if necessary.
1068 Node * LibraryCallKit::pop_math_arg() {
1069 Node *arg = pop_pair();
1070 if( Matcher::strict_fp_requires_explicit_rounding && UseSSE<=1 )
1071 arg = _gvn.transform( new (C, 2) RoundDoubleNode(0, arg) );
1072 return arg;
1073 }
1074
1075 //------------------------------inline_trig----------------------------------
1076 // Inline sin/cos/tan instructions, if possible. If rounding is required, do
1077 // argument reduction which will turn into a fast/slow diamond.
1078 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1079 _sp += arg_size(); // restore stack pointer
1080 Node* arg = pop_math_arg();
|
119 return generate_array_guard_common(kls, region, true, false);
120 }
121 Node* generate_non_objArray_guard(Node* kls, RegionNode* region) {
122 return generate_array_guard_common(kls, region, true, true);
123 }
124 Node* generate_array_guard_common(Node* kls, RegionNode* region,
125 bool obj_array, bool not_array);
126 Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region);
127 CallJavaNode* generate_method_call(vmIntrinsics::ID method_id,
128 bool is_virtual = false, bool is_static = false);
129 CallJavaNode* generate_method_call_static(vmIntrinsics::ID method_id) {
130 return generate_method_call(method_id, false, true);
131 }
132 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
133 return generate_method_call(method_id, true, false);
134 }
135
136 bool inline_string_compareTo();
137 bool inline_string_indexOf();
138 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
139 bool inline_string_equals();
140 Node* pop_math_arg();
141 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
142 bool inline_math_native(vmIntrinsics::ID id);
143 bool inline_trig(vmIntrinsics::ID id);
144 bool inline_trans(vmIntrinsics::ID id);
145 bool inline_abs(vmIntrinsics::ID id);
146 bool inline_sqrt(vmIntrinsics::ID id);
147 bool inline_pow(vmIntrinsics::ID id);
148 bool inline_exp(vmIntrinsics::ID id);
149 bool inline_min_max(vmIntrinsics::ID id);
150 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y);
151 // This returns Type::AnyPtr, RawPtr, or OopPtr.
152 int classify_unsafe_addr(Node* &base, Node* &offset);
153 Node* make_unsafe_address(Node* base, Node* offset);
154 bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile);
155 bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static);
156 bool inline_unsafe_allocate();
157 bool inline_unsafe_copyMemory();
158 bool inline_native_currentThread();
159 bool inline_native_time_funcs(bool isNano);
244 }
245
246 // Only a few intrinsics implement a virtual dispatch.
247 // They are expensive calls which are also frequently overridden.
248 if (is_virtual) {
249 switch (id) {
250 case vmIntrinsics::_hashCode:
251 case vmIntrinsics::_clone:
252 // OK, Object.hashCode and Object.clone intrinsics come in both flavors
253 break;
254 default:
255 return NULL;
256 }
257 }
258
259 // -XX:-InlineNatives disables nearly all intrinsics:
260 if (!InlineNatives) {
261 switch (id) {
262 case vmIntrinsics::_indexOf:
263 case vmIntrinsics::_compareTo:
264 case vmIntrinsics::_equals:
265 case vmIntrinsics::_equalsC:
266 break; // InlineNatives does not control String.compareTo
267 default:
268 return NULL;
269 }
270 }
271
272 switch (id) {
273 case vmIntrinsics::_compareTo:
274 if (!SpecialStringCompareTo) return NULL;
275 break;
276 case vmIntrinsics::_indexOf:
277 if (!SpecialStringIndexOf) return NULL;
278 break;
279 case vmIntrinsics::_equals:
280 if (!SpecialStringEquals) return NULL;
281 break;
282 case vmIntrinsics::_equalsC:
283 if (!SpecialArraysEquals) return NULL;
284 break;
285 case vmIntrinsics::_arraycopy:
286 if (!InlineArrayCopy) return NULL;
287 break;
288 case vmIntrinsics::_copyMemory:
289 if (StubRoutines::unsafe_arraycopy() == NULL) return NULL;
290 if (!InlineArrayCopy) return NULL;
291 break;
292 case vmIntrinsics::_hashCode:
293 if (!InlineObjectHash) return NULL;
294 break;
295 case vmIntrinsics::_clone:
296 case vmIntrinsics::_copyOf:
297 case vmIntrinsics::_copyOfRange:
298 if (!InlineObjectCopy) return NULL;
299 // These also use the arraycopy intrinsic mechanism:
300 if (!InlineArrayCopy) return NULL;
301 break;
424 case vmIntrinsics::_dabs:
425 case vmIntrinsics::_datan2:
426 case vmIntrinsics::_dsqrt:
427 case vmIntrinsics::_dexp:
428 case vmIntrinsics::_dlog:
429 case vmIntrinsics::_dlog10:
430 case vmIntrinsics::_dpow:
431 return inline_math_native(intrinsic_id());
432
433 case vmIntrinsics::_min:
434 case vmIntrinsics::_max:
435 return inline_min_max(intrinsic_id());
436
437 case vmIntrinsics::_arraycopy:
438 return inline_arraycopy();
439
440 case vmIntrinsics::_compareTo:
441 return inline_string_compareTo();
442 case vmIntrinsics::_indexOf:
443 return inline_string_indexOf();
444 case vmIntrinsics::_equals:
445 return inline_string_equals();
446
447 case vmIntrinsics::_getObject:
448 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false);
449 case vmIntrinsics::_getBoolean:
450 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false);
451 case vmIntrinsics::_getByte:
452 return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, false);
453 case vmIntrinsics::_getShort:
454 return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, false);
455 case vmIntrinsics::_getChar:
456 return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, false);
457 case vmIntrinsics::_getInt:
458 return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, false);
459 case vmIntrinsics::_getLong:
460 return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, false);
461 case vmIntrinsics::_getFloat:
462 return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, false);
463 case vmIntrinsics::_getDouble:
464 return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, false);
465
810 return true;
811 }
812
813 ciInstanceKlass* klass = env()->String_klass();
814 const TypeInstPtr* string_type =
815 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
816
817 Node* compare =
818 _gvn.transform(new (C, 7) StrCompNode(
819 control(),
820 memory(TypeAryPtr::CHARS),
821 memory(string_type->add_offset(value_offset)),
822 memory(string_type->add_offset(count_offset)),
823 memory(string_type->add_offset(offset_offset)),
824 receiver,
825 argument));
826 push(compare);
827 return true;
828 }
829
830 //------------------------------inline_string_equals------------------------
831 bool LibraryCallKit::inline_string_equals() {
832
833 if (!Matcher::has_match_rule(Op_StrEquals)) return false;
834
835 const int value_offset = java_lang_String::value_offset_in_bytes();
836 const int count_offset = java_lang_String::count_offset_in_bytes();
837 const int offset_offset = java_lang_String::offset_offset_in_bytes();
838
839 _sp += 2;
840 Node* argument = pop(); // pop non-receiver first: it was pushed second
841 Node* receiver = pop();
842
843
844 // Null check on self without removing any arguments. The argument
845 // null check technically happens in the wrong place, which can lead to
846 // invalid stack traces when string compare is inlined into a method
847 // which handles NullPointerExceptions.
848 _sp += 2;
849 receiver = do_null_check(receiver, T_OBJECT);
850 //should not do null check for argument for String.equals(), because spec
851 //allows to specify NULL as argument.
852 _sp -= 2;
853 if (stopped()) {
854 return true;
855 }
856
857 // get String klass for instanceOf
858 ciInstanceKlass* klass = env()->String_klass();
859
860 // two paths (plus control) merge
861 RegionNode* region = new (C, 3) RegionNode(3);
862 Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL);
863
864 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
865 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1)));
866 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq));
867
868 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN);
869
870 Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff));
871 set_control(if_true);
872
873 const TypeInstPtr* string_type =
874 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
875
876 // instanceOf == true
877 Node* equals =
878 _gvn.transform(new (C, 7) StrEqualsNode(
879 control(),
880 memory(TypeAryPtr::CHARS),
881 memory(string_type->add_offset(value_offset)),
882 memory(string_type->add_offset(count_offset)),
883 memory(string_type->add_offset(offset_offset)),
884 receiver,
885 argument));
886
887 phi->init_req(1, _gvn.transform(equals));
888 region->init_req(1, if_true);
889
890 //instanceOf == false, fallthrough
891 Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff));
892 set_control(if_false);
893
894 phi->init_req(2, _gvn.transform(intcon(0)));
895 region->init_req(2, if_false);
896
897 // post merge
898 set_control(_gvn.transform(region));
899 record_for_igvn(region);
900
901 push(_gvn.transform(phi));
902
903 return true;
904 }
905
906 //------------------------------inline_array_equals----------------------------
907 bool LibraryCallKit::inline_array_equals() {
908
909 if (!Matcher::has_match_rule(Op_AryEq)) return false;
910
911 _sp += 2;
912 Node *argument2 = pop();
913 Node *argument1 = pop();
914
915 Node* equals =
916 _gvn.transform(new (C, 3) AryEqNode(control(),
917 argument1,
918 argument2)
919 );
920 push(equals);
921 return true;
922 }
923
924 // Java version of String.indexOf(constant string)
925 // class StringDecl {
1050 }__ end_loop(); __ dead(j);
1051 __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i);
1052 __ goto_(return_);
1053 }__ end_if();
1054 __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); {
1055 __ increment(i, targetCountLess1);
1056 }__ end_if();
1057 __ increment(i, one);
1058 __ bind(outer_loop);
1059 }__ end_loop(); __ dead(i);
1060 __ bind(return_);
1061 __ drain_delay_transform();
1062
1063 set_control(__ ctrl());
1064 Node* result = __ value(rtn);
1065 #undef __
1066 C->set_has_loops(true);
1067 return result;
1068 }
1069
1070 //------------------------------inline_string_indexOf------------------------
1071 bool LibraryCallKit::inline_string_indexOf() {
1072
1073 _sp += 2;
1074 Node *argument = pop(); // pop non-receiver first: it was pushed second
1075 Node *receiver = pop();
1076
1077 // don't intrinsify is argument isn't a constant string.
1078 if (!argument->is_Con()) {
1079 return false;
1080 }
1081 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr();
1082 if (str_type == NULL) {
1083 return false;
1084 }
1085 ciInstanceKlass* klass = env()->String_klass();
1086 ciObject* str_const = str_type->const_oop();
1087 if (str_const == NULL || str_const->klass() != klass) {
1088 return false;
1089 }
1106 }
1107
1108 // Null check on self without removing any arguments. The argument
1109 // null check technically happens in the wrong place, which can lead to
1110 // invalid stack traces when string compare is inlined into a method
1111 // which handles NullPointerExceptions.
1112 _sp += 2;
1113 receiver = do_null_check(receiver, T_OBJECT);
1114 // No null check on the argument is needed since it's a constant String oop.
1115 _sp -= 2;
1116 if (stopped()) {
1117 return true;
1118 }
1119
1120 // The null string as a pattern always returns 0 (match at beginning of string)
1121 if (c == 0) {
1122 push(intcon(0));
1123 return true;
1124 }
1125
1126 Node* result;
1127 if (Matcher::has_match_rule(Op_StrIndexOf) &&
1128 UseSSE >= 4 && UseSSE42Intrinsics) {
1129 // Generate SSE4.2 version of indexOf
1130 // We currently only have match rules that use SSE4.2
1131 const TypeInstPtr* string_type =
1132 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0);
1133
1134 result =
1135 _gvn.transform(new (C, 7)
1136 StrIndexOfNode(control(),
1137 memory(TypeAryPtr::CHARS),
1138 memory(string_type->add_offset(value_offset)),
1139 memory(string_type->add_offset(count_offset)),
1140 memory(string_type->add_offset(offset_offset)),
1141 receiver,
1142 argument));
1143 } else {
1144 // Generate default indexOf
1145 jchar lastChar = pat->char_at(o + (c - 1));
1146 int cache = 0;
1147 int i;
1148 for (i = 0; i < c - 1; i++) {
1149 assert(i < pat->length(), "out of range");
1150 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
1151 }
1152
1153 int md2 = c;
1154 for (i = 0; i < c - 1; i++) {
1155 assert(i < pat->length(), "out of range");
1156 if (pat->char_at(o + i) == lastChar) {
1157 md2 = (c - 1) - i;
1158 }
1159 }
1160
1161 result = string_indexOf(receiver, pat, o, cache, md2);
1162 }
1163 push(result);
1164 return true;
1165 }
1166
1167 //--------------------------pop_math_arg--------------------------------
1168 // Pop a double argument to a math function from the stack
1169 // rounding it if necessary.
1170 Node * LibraryCallKit::pop_math_arg() {
1171 Node *arg = pop_pair();
1172 if( Matcher::strict_fp_requires_explicit_rounding && UseSSE<=1 )
1173 arg = _gvn.transform( new (C, 2) RoundDoubleNode(0, arg) );
1174 return arg;
1175 }
1176
1177 //------------------------------inline_trig----------------------------------
1178 // Inline sin/cos/tan instructions, if possible. If rounding is required, do
1179 // argument reduction which will turn into a fast/slow diamond.
1180 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1181 _sp += arg_size(); // restore stack pointer
1182 Node* arg = pop_math_arg();
|