--- old/make/data/characterdata/CharacterData00.java.template 2018-12-06 01:19:36.848159912 -0600 +++ new/make/data/characterdata/CharacterData00.java.template 2018-12-06 01:19:36.248179772 -0600 @@ -754,6 +754,18 @@ return retval; } + boolean isDigit(int ch) { + return getType(ch) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + return getType(ch) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + return getType(ch) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace); --- old/make/data/characterdata/CharacterData01.java.template 2018-12-06 01:19:38.848093712 -0600 +++ new/make/data/characterdata/CharacterData01.java.template 2018-12-06 01:19:38.248113572 -0600 @@ -460,6 +460,18 @@ return retval; } + boolean isDigit(int ch) { + return getType(ch) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + return getType(ch) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + return getType(ch) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace); --- old/make/data/characterdata/CharacterData02.java.template 2018-12-06 01:19:40.378043069 -0600 +++ new/make/data/characterdata/CharacterData02.java.template 2018-12-06 01:19:39.778062929 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,6 +217,18 @@ return retval; } + boolean isDigit(int ch) { + return getType(ch) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + return getType(ch) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + return getType(ch) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { return (getProperties(ch) & $$maskIdentifierInfo) == $$valueJavaWhitespace; } --- old/make/data/characterdata/CharacterData0E.java.template 2018-12-06 01:19:41.438007983 -0600 +++ new/make/data/characterdata/CharacterData0E.java.template 2018-12-06 01:19:40.838027843 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,6 +217,18 @@ return retval; } + boolean isDigit(int ch) { + return getType(ch) == Character.DECIMAL_DIGIT_NUMBER; + } + + boolean isLowerCase(int ch) { + return getType(ch) == Character.LOWERCASE_LETTER; + } + + boolean isUpperCase(int ch) { + return getType(ch) == Character.UPPERCASE_LETTER; + } + boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace); --- old/make/data/characterdata/CharacterDataLatin1.java.template 2018-12-06 01:19:42.507972566 -0600 +++ new/make/data/characterdata/CharacterDataLatin1.java.template 2018-12-06 01:19:41.907992426 -0600 @@ -25,6 +25,8 @@ package java.lang; +import jdk.internal.HotSpotIntrinsicCandidate; + /** The CharacterData class encapsulates the large tables found in Java.lang.Character. */ @@ -78,6 +80,21 @@ return props; } + @HotSpotIntrinsicCandidate + boolean isDigit(int ch) { + return getType(ch) == Character.DECIMAL_DIGIT_NUMBER; + } + + @HotSpotIntrinsicCandidate + boolean isLowerCase(int ch) { + return getType(ch) == Character.LOWERCASE_LETTER; + } + + @HotSpotIntrinsicCandidate + boolean isUpperCase(int ch) { + return getType(ch) == Character.UPPERCASE_LETTER; + } + boolean isOtherLowercase(int ch) { int props = getPropertiesEx(ch); return (props & $$maskOtherLowercase) != 0; @@ -214,6 +231,7 @@ return retval; } + @HotSpotIntrinsicCandidate boolean isWhitespace(int ch) { int props = getProperties(ch); return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace); --- old/make/data/characterdata/CharacterDataPrivateUse.java.template 2018-12-06 01:19:43.577937149 -0600 +++ new/make/data/characterdata/CharacterDataPrivateUse.java.template 2018-12-06 01:19:42.977957009 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,47 +41,59 @@ } boolean isJavaIdentifierStart(int ch) { - return false; + return false; } boolean isJavaIdentifierPart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierStart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierPart(int ch) { - return false; + return false; } boolean isIdentifierIgnorable(int ch) { - return false; + return false; } int toLowerCase(int ch) { - return ch; + return ch; } int toUpperCase(int ch) { - return ch; + return ch; } int toTitleCase(int ch) { - return ch; + return ch; } int digit(int ch, int radix) { - return -1; + return -1; } int getNumericValue(int ch) { - return -1; + return -1; + } + + boolean isDigit(int ch) { + return false; + } + + boolean isLowerCase(int ch) { + return false; + } + + boolean isUpperCase(int ch) { + return false; } boolean isWhitespace(int ch) { - return false; + return false; } byte getDirectionality(int ch) { @@ -91,7 +103,7 @@ } boolean isMirrored(int ch) { - return false; + return false; } static final CharacterData instance = new CharacterDataPrivateUse(); --- old/make/data/characterdata/CharacterDataUndefined.java.template 2018-12-06 01:19:44.667901070 -0600 +++ new/make/data/characterdata/CharacterDataUndefined.java.template 2018-12-06 01:19:44.067920930 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,59 +35,71 @@ } int getType(int ch) { - return Character.UNASSIGNED; + return Character.UNASSIGNED; } boolean isJavaIdentifierStart(int ch) { - return false; + return false; } boolean isJavaIdentifierPart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierStart(int ch) { - return false; + return false; } boolean isUnicodeIdentifierPart(int ch) { - return false; + return false; } boolean isIdentifierIgnorable(int ch) { - return false; + return false; } int toLowerCase(int ch) { - return ch; + return ch; } int toUpperCase(int ch) { - return ch; + return ch; } int toTitleCase(int ch) { - return ch; + return ch; } int digit(int ch, int radix) { - return -1; + return -1; } int getNumericValue(int ch) { - return -1; + return -1; + } + + boolean isDigit(int ch) { + return false; + } + + boolean isLowerCase(int ch) { + return false; + } + + boolean isUpperCase(int ch) { + return false; } boolean isWhitespace(int ch) { - return false; + return false; } byte getDirectionality(int ch) { - return Character.DIRECTIONALITY_UNDEFINED; + return Character.DIRECTIONALITY_UNDEFINED; } boolean isMirrored(int ch) { - return false; + return false; } static final CharacterData instance = new CharacterDataUndefined(); --- old/src/hotspot/cpu/ppc/assembler_ppc.hpp 2018-12-06 01:19:46.227849434 -0600 +++ new/src/hotspot/cpu/ppc/assembler_ppc.hpp 2018-12-06 01:19:45.627869294 -0600 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -299,6 +299,8 @@ CMPI_OPCODE = (11u << OPCODE_SHIFT), CMPL_OPCODE = (31u << OPCODE_SHIFT | 32u << 1), CMPLI_OPCODE = (10u << OPCODE_SHIFT), + CMPRB_OPCODE = (31u << OPCODE_SHIFT | 192u << 1), + CMPEQB_OPCODE = (31u << OPCODE_SHIFT | 224u << 1), ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), @@ -336,6 +338,7 @@ MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), MCRF_OPCODE = (19u << OPCODE_SHIFT | 0u << 1), + SETB_OPCODE = (31u << OPCODE_SHIFT | 128u << 1), // condition register logic instructions CRAND_OPCODE = (19u << OPCODE_SHIFT | 257u << 1), @@ -1076,7 +1079,7 @@ static int frs( int x) { return opp_u_field(x, 10, 6); } static int frt( int x) { return opp_u_field(x, 10, 6); } static int fxm( int x) { return opp_u_field(x, 19, 12); } - static int l10( int x) { return opp_u_field(x, 10, 10); } + static int l10( int x) { assert(x == 0 || x == 1, "must be 0 or 1"); return opp_u_field(x, 10, 10); } static int l14( int x) { return opp_u_field(x, 15, 14); } static int l15( int x) { return opp_u_field(x, 15, 15); } static int l910( int x) { return opp_u_field(x, 10, 9); } @@ -1443,6 +1446,10 @@ inline void cmplw( ConditionRegister crx, Register a, Register b); inline void cmpld( ConditionRegister crx, Register a, Register b); + // >= Power9 + inline void cmprb( ConditionRegister bf, int l, Register a, Register b); + inline void cmpeqb(ConditionRegister bf, Register a, Register b); + inline void isel( Register d, Register a, Register b, int bc); // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value. inline void isel( Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg); @@ -1642,6 +1649,8 @@ inline void mfcr( Register d); inline void mcrf( ConditionRegister crd, ConditionRegister cra); inline void mtcr( Register s); + // >= Power9 + inline void setb( Register d, ConditionRegister cra); // Special purpose registers // Exception Register --- old/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp 2018-12-06 01:19:48.277781579 -0600 +++ new/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp 2018-12-06 01:19:47.677801439 -0600 @@ -171,6 +171,8 @@ inline void Assembler::cmp( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMP_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } inline void Assembler::cmpli( ConditionRegister f, int l, Register a, int ui16) { emit_int32( CMPLI_OPCODE | bf(f) | l10(l) | ra(a) | uimm(ui16,16)); } inline void Assembler::cmpl( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPL_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } +inline void Assembler::cmprb( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPRB_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); } +inline void Assembler::cmpeqb(ConditionRegister f, Register a, Register b) { emit_int32( CMPEQB_OPCODE| bf(f) | ra(a) | rb(b)); } // extended mnemonics of Compare Instructions inline void Assembler::cmpwi( ConditionRegister crx, Register a, int si16) { Assembler::cmpi( crx, 0, a, si16); } @@ -371,6 +373,8 @@ inline void Assembler::mcrf( ConditionRegister crd, ConditionRegister cra) { emit_int32(MCRF_OPCODE | bf(crd) | bfa(cra)); } inline void Assembler::mtcr( Register s) { Assembler::mtcrf(0xff, s); } +inline void Assembler::setb(Register d, ConditionRegister cra) + { emit_int32(SETB_OPCODE | rt(d) | bfa(cra)); } // Special purpose registers // Exception Register --- old/src/hotspot/cpu/ppc/ppc.ad 2018-12-06 01:19:50.297714717 -0600 +++ new/src/hotspot/cpu/ppc/ppc.ad 2018-12-06 01:19:49.687734908 -0600 @@ -2257,6 +2257,11 @@ return SuperwordUseVSX; case Op_PopCountVI: return (SuperwordUseVSX && UsePopCountInstruction); + case Op_Digit: + case Op_LowerCase: + case Op_UpperCase: + case Op_Whitespace: + return VM_Version::has_darn(); } return true; // Per default match rules are supported. @@ -12400,6 +12405,130 @@ %} %} +// Compare char +instruct cmprb_Digit_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (Digit src1)); + effect(TEMP src2, TEMP crx); + ins_cost(3 * DEFAULT_COST); + + format %{ "LI $src2, 0x3930\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "SETB $dst, $crx" %} + size(12); + ins_encode %{ + // 0x30: 0, 0x39: 9 + __ li($src2$$Register, 0x3930); + // compare src1 with ranges 0x30 to 0x39 + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_LowerCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (LowerCase src1)); + effect(TEMP src2, TEMP crx); + ins_cost(12 * DEFAULT_COST); + + format %{ "LI $src2, 0x7A61\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xF6DF\n\t" + "ORI $src2, $src2, 0xFFF8\n\t" + "CMPRB $crx, 1, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xAAB5\n\t" + "ORI $src2, $src2, 0xBABA\n\t" + "INSRDI $src2, $src2, 32, 0\n\t" + "CMPEQB $crx, 1, $src1, $src2\n\t" + "SETB $dst, $crx" %} + + size(48); + ins_encode %{ + Label done; + // 0x61: a, 0x7A: z + __ li($src2$$Register, 0x7A61); + // compare src1 with ranges 0x61 to 0x7A + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xDF: sharp s, 0xFF: y with diaeresis, 0xF7 is not the lower case + __ lis($src2$$Register, (signed short)0xF6DF); + __ ori($src2$$Register, $src2$$Register, 0xFFF8); + // compare src1 with ranges 0xDF to 0xF6 and 0xF8 to 0xFF + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xAA: feminine ordinal indicator + // 0xB5: micro sign + // 0xBA: masculine ordinal indicator + __ lis($src2$$Register, (signed short)0xAAB5); + __ ori($src2$$Register, $src2$$Register, 0xBABA); + __ insrdi($src2$$Register, $src2$$Register, 32, 0); + // compare src1 with 0xAA, 0xB5, and 0xBA + __ cmpeqb($crx$$CondRegister, $src1$$Register, $src2$$Register); + + __ bind(done); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_UpperCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (UpperCase src1)); + effect(TEMP src2, TEMP crx); + ins_cost(7 * DEFAULT_COST); + + format %{ "LI $src2, 0x5A41\n\t" + "CMPRB $crx, 0, $src1, $src2\n\t" + "BGT $crx, done\n\t" + "LIS $src2, (signed short)0xD6C0\n\t" + "ORI $src2, $src2, 0xDED8\n\t" + "CMPRB $crx, 1, $src1, $src2\n\t" + "SETB $dst, $crx" %} + + size(28); + ins_encode %{ + Label done; + // 0x41: A, 0x5A: Z + __ li($src2$$Register, 0x5A41); + // compare src1 with a range 0x41 to 0x5A + __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register); + __ bgt($crx$$CondRegister, done); + + // 0xC0: a with grave, 0xDE: thorn, 0xD7 is not the upper case + __ lis($src2$$Register, (signed short)0xD6C0); + __ ori($src2$$Register, $src2$$Register, 0xDED8); + // compare src1 with ranges 0xC0 to 0xD6 and 0xD8 to 0xDE + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + + __ bind(done); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + +instruct cmprb_Whitespace_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{ + match(Set dst (Whitespace src1)); + effect(TEMP src2, TEMP crx); + ins_cost(4 * DEFAULT_COST); + + format %{ "LI $src2, 0x0D09\n\t" + "ADDIS $src2, 0x201C\n\t" + "CMPRB $crx, 1, $src1, $src2\n\t" + "SETB $dst, $crx" %} + size(16); + ins_encode %{ + // 0x09 to 0x0D, 0x1C to 0x20 + __ li($src2$$Register, 0x0D09); + __ addis($src2$$Register, $src2$$Register, 0x0201C); + // compare src with ranges 0x09 to 0x0D and 0x1C to 0x20 + __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register); + __ setb($dst$$Register, $crx$$CondRegister); + %} + ins_pipe(pipe_class_default); +%} + //----------Branches--------------------------------------------------------- // Jump --- old/src/hotspot/share/classfile/vmSymbols.cpp 2018-12-06 01:19:52.227650834 -0600 +++ new/src/hotspot/share/classfile/vmSymbols.cpp 2018-12-06 01:19:51.617671025 -0600 @@ -379,6 +379,10 @@ case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_fmaD: case vmIntrinsics::_fmaF: + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: return true; default: return false; @@ -827,6 +831,12 @@ case vmIntrinsics::_subtractExactL: if (!UseMathExactIntrinsics || !InlineMathNatives) return true; break; + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + if (!UseCharacterCompareIntrinsics) return true; + break; #endif // COMPILER2 default: return false; --- old/src/hotspot/share/classfile/vmSymbols.hpp 2018-12-06 01:19:53.777599529 -0600 +++ new/src/hotspot/share/classfile/vmSymbols.hpp 2018-12-06 01:19:53.177619389 -0600 @@ -71,6 +71,7 @@ template(java_lang_Boolean, "java/lang/Boolean") \ template(java_lang_Character, "java/lang/Character") \ template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \ + template(java_lang_CharacterDataLatin1, "java/lang/CharacterDataLatin1") \ template(java_lang_Float, "java/lang/Float") \ template(java_lang_Double, "java/lang/Double") \ template(java_lang_Byte, "java/lang/Byte") \ @@ -933,6 +934,15 @@ do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \ do_intrinsic(_equalsU, java_lang_StringUTF16, equals_name, equalsB_signature, F_S) \ \ + do_intrinsic(_isDigit, java_lang_CharacterDataLatin1, isDigit_name, int_bool_signature, F_R) \ + do_name( isDigit_name, "isDigit") \ + do_intrinsic(_isLowerCase, java_lang_CharacterDataLatin1, isLowerCase_name, int_bool_signature, F_R) \ + do_name( isLowerCase_name, "isLowerCase") \ + do_intrinsic(_isUpperCase, java_lang_CharacterDataLatin1, isUpperCase_name, int_bool_signature, F_R) \ + do_name( isUpperCase_name, "isUpperCase") \ + do_intrinsic(_isWhitespace, java_lang_CharacterDataLatin1, isWhitespace_name, int_bool_signature, F_R) \ + do_name( isWhitespace_name, "isWhitespace") \ + \ do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S) \ do_signature(Preconditions_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \ \ --- old/src/hotspot/share/opto/c2_globals.hpp 2018-12-06 01:19:55.347547562 -0600 +++ new/src/hotspot/share/opto/c2_globals.hpp 2018-12-06 01:19:54.747567422 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -710,6 +710,9 @@ diagnostic(bool, UseMathExactIntrinsics, true, \ "Enables intrinsification of various java.lang.Math functions") \ \ + diagnostic(bool, UseCharacterCompareIntrinsics, false, \ + "Enables intrinsification of java.lang.Character functions") \ + \ diagnostic(bool, UseMultiplyToLenIntrinsic, false, \ "Enables intrinsification of BigInteger.multiplyToLen()") \ \ --- old/src/hotspot/share/opto/c2compiler.cpp 2018-12-06 01:19:56.517508835 -0600 +++ new/src/hotspot/share/opto/c2compiler.cpp 2018-12-06 01:19:55.907529026 -0600 @@ -428,6 +428,18 @@ case vmIntrinsics::_fmaF: if (!UseFMA || !Matcher::match_rule_supported(Op_FmaF)) return false; break; + case vmIntrinsics::_isDigit: + if (!Matcher::match_rule_supported(Op_Digit)) return false; + break; + case vmIntrinsics::_isLowerCase: + if (!Matcher::match_rule_supported(Op_LowerCase)) return false; + break; + case vmIntrinsics::_isUpperCase: + if (!Matcher::match_rule_supported(Op_UpperCase)) return false; + break; + case vmIntrinsics::_isWhitespace: + if (!Matcher::match_rule_supported(Op_Whitespace)) return false; + break; case vmIntrinsics::_hashCode: case vmIntrinsics::_identityHashCode: case vmIntrinsics::_getClass: --- old/src/hotspot/share/opto/classes.hpp 2018-12-06 01:19:57.597473087 -0600 +++ new/src/hotspot/share/opto/classes.hpp 2018-12-06 01:19:56.987493278 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -379,3 +379,7 @@ macro(ExtractL) macro(ExtractF) macro(ExtractD) +macro(Digit) +macro(LowerCase) +macro(UpperCase) +macro(Whitespace) --- old/src/hotspot/share/opto/intrinsicnode.hpp 2018-12-06 01:19:58.667437670 -0600 +++ new/src/hotspot/share/opto/intrinsicnode.hpp 2018-12-06 01:19:58.067457530 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,4 +180,40 @@ virtual const Type* Value(PhaseGVN* phase) const; }; +//-------------------------------DigitNode---------------------------------------- +class DigitNode : public Node { +public: + DigitNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------LowerCaseNode------------------------------------ +class LowerCaseNode : public Node { +public: + LowerCaseNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------UpperCaseNode------------------------------------ +class UpperCaseNode : public Node { +public: + UpperCaseNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//------------------------------WhitespaceCode----------------------------------- +class WhitespaceNode : public Node { +public: + WhitespaceNode(Node* control, Node *in1) : Node(control, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::BOOL; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + #endif // SHARE_VM_OPTO_INTRINSICNODE_HPP --- old/src/hotspot/share/opto/library_call.cpp 2018-12-06 01:19:59.737402253 -0600 +++ new/src/hotspot/share/opto/library_call.cpp 2018-12-06 01:19:59.127422444 -0600 @@ -324,6 +324,7 @@ bool inline_montgomerySquare(); bool inline_vectorizedMismatch(); bool inline_fma(vmIntrinsics::ID id); + bool inline_character_compare(vmIntrinsics::ID id); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -867,6 +868,12 @@ case vmIntrinsics::_fmaF: return inline_fma(intrinsic_id()); + case vmIntrinsics::_isDigit: + case vmIntrinsics::_isLowerCase: + case vmIntrinsics::_isUpperCase: + case vmIntrinsics::_isWhitespace: + return inline_character_compare(intrinsic_id()); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -6555,6 +6562,32 @@ return true; } +bool LibraryCallKit::inline_character_compare(vmIntrinsics::ID id) { + // argument(0) is receiver + Node* codePoint = argument(1); + Node* n = NULL; + + switch (id) { + case vmIntrinsics::_isDigit : + n = new DigitNode(control(), codePoint); + break; + case vmIntrinsics::_isLowerCase : + n = new LowerCaseNode(control(), codePoint); + break; + case vmIntrinsics::_isUpperCase : + n = new UpperCaseNode(control(), codePoint); + break; + case vmIntrinsics::_isWhitespace : + n = new WhitespaceNode(control(), codePoint); + break; + default: + fatal_unexpected_iid(id); + } + + set_result(_gvn.transform(n)); + return true; +} + bool LibraryCallKit::inline_profileBoolean() { Node* counts = argument(1); const TypeAryPtr* ary = NULL; --- old/src/java.base/share/classes/java/lang/Character.java 2018-12-06 01:20:01.447345652 -0600 +++ new/src/java.base/share/classes/java/lang/Character.java 2018-12-06 01:20:00.837365843 -0600 @@ -9084,7 +9084,7 @@ * @since 1.5 */ public static boolean isLowerCase(int codePoint) { - return getType(codePoint) == Character.LOWERCASE_LETTER || + return CharacterData.of(codePoint).isLowerCase(codePoint) || CharacterData.of(codePoint).isOtherLowercase(codePoint); } @@ -9150,7 +9150,7 @@ * @since 1.5 */ public static boolean isUpperCase(int codePoint) { - return getType(codePoint) == Character.UPPERCASE_LETTER || + return CharacterData.of(codePoint).isUpperCase(codePoint) || CharacterData.of(codePoint).isOtherUppercase(codePoint); } @@ -9301,7 +9301,7 @@ * @since 1.5 */ public static boolean isDigit(int codePoint) { - return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER; + return CharacterData.of(codePoint).isDigit(codePoint); } /** --- old/src/java.base/share/classes/java/lang/CharacterData.java 2018-12-06 01:20:03.247286072 -0600 +++ new/src/java.base/share/classes/java/lang/CharacterData.java 2018-12-06 01:20:02.647305932 -0600 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,9 @@ abstract class CharacterData { abstract int getProperties(int ch); abstract int getType(int ch); + abstract boolean isDigit(int ch); + abstract boolean isLowerCase(int ch); + abstract boolean isUpperCase(int ch); abstract boolean isWhitespace(int ch); abstract boolean isMirrored(int ch); abstract boolean isJavaIdentifierStart(int ch); --- /dev/null 2018-09-28 17:19:28.940000000 -0500 +++ new/test/micro/org/openjdk/bench/java/lang/Characters.java 2018-12-06 01:20:03.707270846 -0600 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class Characters { + + @Param({"9", "48", "65", "97", "170", "192", "223", "256"}) + private int codePoint; + + @Benchmark + public boolean isDigit() { + return Character.isDigit(codePoint); + } + + @Benchmark + public boolean isLowerCase() { + return Character.isLowerCase(codePoint); + } + + @Benchmark + public boolean isUpperCase() { + return Character.isUpperCase(codePoint); + } + + @Benchmark + public boolean isWhitespace() { + return Character.isWhitespace(codePoint); + } +}