--- old/make/data/characterdata/CharacterData00.java.template 2018-12-03 22:19:57.946073281 -0600 +++ new/make/data/characterdata/CharacterData00.java.template 2018-12-03 22:19:57.346093141 -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-03 22:19:59.966006419 -0600 +++ new/make/data/characterdata/CharacterData01.java.template 2018-12-03 22:19:59.366026279 -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-03 22:20:01.525954783 -0600 +++ new/make/data/characterdata/CharacterData02.java.template 2018-12-03 22:20:00.915974974 -0600 @@ -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-03 22:20:02.615918704 -0600 +++ new/make/data/characterdata/CharacterData0E.java.template 2018-12-03 22:20:02.015938564 -0600 @@ -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-03 22:20:03.695882956 -0600 +++ new/make/data/characterdata/CharacterDataLatin1.java.template 2018-12-03 22:20:03.105902485 -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-03 22:20:04.795846546 -0600 +++ new/make/data/characterdata/CharacterDataPrivateUse.java.template 2018-12-03 22:20:04.195866406 -0600 @@ -80,6 +80,18 @@ 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; } --- old/make/data/characterdata/CharacterDataUndefined.java.template 2018-12-03 22:20:05.885810467 -0600 +++ new/make/data/characterdata/CharacterDataUndefined.java.template 2018-12-03 22:20:05.285830327 -0600 @@ -78,6 +78,18 @@ 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; } --- old/src/hotspot/cpu/ppc/assembler_ppc.hpp 2018-12-03 22:20:07.445758831 -0600 +++ new/src/hotspot/cpu/ppc/assembler_ppc.hpp 2018-12-03 22:20:06.835779022 -0600 @@ -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-03 22:20:09.495690976 -0600 +++ new/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp 2018-12-03 22:20:08.885711167 -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-03 22:20:11.505624445 -0600 +++ new/src/hotspot/cpu/ppc/ppc.ad 2018-12-03 22:20:10.895644636 -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-03 22:20:13.435560562 -0600 +++ new/src/hotspot/share/classfile/vmSymbols.cpp 2018-12-03 22:20:12.825580753 -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-03 22:20:15.005508595 -0600 +++ new/src/hotspot/share/classfile/vmSymbols.hpp 2018-12-03 22:20:14.405528455 -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-03 22:20:16.575456628 -0600 +++ new/src/hotspot/share/opto/c2_globals.hpp 2018-12-03 22:20:15.965476819 -0600 @@ -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-03 22:20:17.675420218 -0600 +++ new/src/hotspot/share/opto/c2compiler.cpp 2018-12-03 22:20:17.065440409 -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-03 22:20:18.745384801 -0600 +++ new/src/hotspot/share/opto/classes.hpp 2018-12-03 22:20:18.145404661 -0600 @@ -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-03 22:20:19.825349053 -0600 +++ new/src/hotspot/share/opto/intrinsicnode.hpp 2018-12-03 22:20:19.215369244 -0600 @@ -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-03 22:20:20.885313967 -0600 +++ new/src/hotspot/share/opto/library_call.cpp 2018-12-03 22:20:20.285333827 -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-03 22:20:22.625256373 -0600 +++ new/src/java.base/share/classes/java/lang/Character.java 2018-12-03 22:20:22.015276564 -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-03 22:20:24.425196793 -0600 +++ new/src/java.base/share/classes/java/lang/CharacterData.java 2018-12-03 22:20:23.815216984 -0600 @@ -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);