8213754: PPC64: Add Intrinsics for isDigit/isLowerCase/isUpperCase/isWhitespace

Reviewed-by: kvn, rriggs, mdoerr, gromero
This commit is contained in:
Michihiro Horie 2018-12-11 20:31:18 -05:00
parent d1ef9b19d7
commit 31fbc28af5
21 changed files with 468 additions and 38 deletions

View File

@ -754,6 +754,21 @@ class CharacterData00 extends CharacterData {
return retval;
}
boolean isDigit(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
}
boolean isLowerCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.LOWERCASE_LETTER;
}
boolean isUpperCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.UPPERCASE_LETTER;
}
boolean isWhitespace(int ch) {
int props = getProperties(ch);
return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);

View File

@ -460,6 +460,21 @@ class CharacterData01 extends CharacterData {
return retval;
}
boolean isDigit(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
}
boolean isLowerCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.LOWERCASE_LETTER;
}
boolean isUpperCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.UPPERCASE_LETTER;
}
boolean isWhitespace(int ch) {
int props = getProperties(ch);
return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);

View File

@ -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,21 @@ class CharacterData02 extends CharacterData {
return retval;
}
boolean isDigit(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
}
boolean isLowerCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.LOWERCASE_LETTER;
}
boolean isUpperCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.UPPERCASE_LETTER;
}
boolean isWhitespace(int ch) {
return (getProperties(ch) & $$maskIdentifierInfo) == $$valueJavaWhitespace;
}

View File

@ -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,21 @@ class CharacterData0E extends CharacterData {
return retval;
}
boolean isDigit(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
}
boolean isLowerCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.LOWERCASE_LETTER;
}
boolean isUpperCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.UPPERCASE_LETTER;
}
boolean isWhitespace(int ch) {
int props = getProperties(ch);
return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);

View File

@ -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,23 @@ class CharacterDataLatin1 extends CharacterData {
return props;
}
@HotSpotIntrinsicCandidate
boolean isDigit(int ch) {
return '0' <= ch && ch <= '9';
}
@HotSpotIntrinsicCandidate
boolean isLowerCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.LOWERCASE_LETTER;
}
@HotSpotIntrinsicCandidate
boolean isUpperCase(int ch) {
int props = getProperties(ch);
return (props & $$maskType) == Character.UPPERCASE_LETTER;
}
boolean isOtherLowercase(int ch) {
int props = getPropertiesEx(ch);
return (props & $$maskOtherLowercase) != 0;
@ -214,6 +233,7 @@ class CharacterDataLatin1 extends CharacterData {
return retval;
}
@HotSpotIntrinsicCandidate
boolean isWhitespace(int ch) {
int props = getProperties(ch);
return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);

View File

@ -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 @@ class CharacterDataPrivateUse extends CharacterData {
}
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 @@ class CharacterDataPrivateUse extends CharacterData {
}
boolean isMirrored(int ch) {
return false;
return false;
}
static final CharacterData instance = new CharacterDataPrivateUse();

View File

@ -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 @@ class CharacterDataUndefined extends CharacterData {
}
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();

View File

@ -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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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

View File

@ -171,6 +171,8 @@ inline void Assembler::cmpi( ConditionRegister f, int l, Register a, int si16)
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::mfcr( Register d ) { emit_int32(MFCR_OPCODE | rt
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

View File

@ -2257,6 +2257,11 @@ const bool Matcher::match_rule_supported(int opcode) {
return SuperwordUseVSX;
case Op_PopCountVI:
return (SuperwordUseVSX && UsePopCountInstruction);
case Op_Digit:
case Op_LowerCase:
case Op_UpperCase:
case Op_Whitespace:
return UseCharacterCompareIntrinsics;
}
return true; // Per default match rules are supported.
@ -12400,6 +12405,132 @@ instruct cmpD3_reg_reg_ExEx(iRegIdst dst, regD src1, regD src2) %{
%}
%}
// 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"
"done:\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"
"done:\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

View File

@ -134,11 +134,18 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionsPPC64)) {
FLAG_SET_ERGO(bool, UseCountTrailingZerosInstructionsPPC64, true);
}
if (FLAG_IS_DEFAULT(UseCharacterCompareIntrinsics)) {
FLAG_SET_ERGO(bool, UseCharacterCompareIntrinsics, true);
}
} else {
if (UseCountTrailingZerosInstructionsPPC64) {
warning("UseCountTrailingZerosInstructionsPPC64 specified, but needs at least Power9.");
FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionsPPC64, false);
}
if (UseCharacterCompareIntrinsics) {
warning("UseCharacterCompareIntrinsics specified, but needs at least Power9.");
FLAG_SET_DEFAULT(UseCharacterCompareIntrinsics, false);
}
}
#endif

View File

@ -379,6 +379,10 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
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;
@ -828,6 +832,12 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
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;

View File

@ -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") \
\

View File

@ -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()") \
\

View File

@ -428,6 +428,18 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
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:

View File

@ -394,3 +394,7 @@ macro(ExtractI)
macro(ExtractL)
macro(ExtractF)
macro(ExtractD)
macro(Digit)
macro(LowerCase)
macro(UpperCase)
macro(Whitespace)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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 @@ class EncodeISOArrayNode: public Node {
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

View File

@ -324,6 +324,7 @@ class LibraryCallKit : public GraphKit {
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 @@ bool LibraryCallKit::try_to_inline(int predicate) {
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 @@ bool LibraryCallKit::inline_fma(vmIntrinsics::ID id) {
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;

View File

@ -9085,7 +9085,7 @@ class Character implements java.io.Serializable, Comparable<Character> {
* @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);
}
@ -9151,7 +9151,7 @@ class Character implements java.io.Serializable, Comparable<Character> {
* @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);
}
@ -9302,7 +9302,7 @@ class Character implements java.io.Serializable, Comparable<Character> {
* @since 1.5
*/
public static boolean isDigit(int codePoint) {
return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
return CharacterData.of(codePoint).isDigit(codePoint);
}
/**

View File

@ -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 @@ package java.lang;
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);

View File

@ -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", "128", "170", "192", "223"})
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);
}
}