Skip to content

Commit eeef4de

Browse files
Dongbo HePaul Hohensee
authored andcommitted
8150669: C1 intrinsic for Class.isPrimitive
Reviewed-by: phh Backport-of: 890f94d7e6be731ac2ebae2f1ad3cc20ec836115
1 parent 6e8292f commit eeef4de

File tree

5 files changed

+198
-1
lines changed

5 files changed

+198
-1
lines changed

hotspot/src/share/vm/c1/c1_Canonicalizer.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
463463
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
464464
if (c != NULL && !c->value()->is_null_object()) {
465465
// ciInstance::java_mirror_type() returns non-NULL only for Java mirrors
466-
ciType* t = c->value()->as_instance()->java_mirror_type();
466+
ciType* t = c->value()->java_mirror_type();
467467
if (t->is_klass()) {
468468
// substitute cls.isInstance(obj) of a constant Class into
469469
// an InstantOf instruction
@@ -479,6 +479,17 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
479479
}
480480
break;
481481
}
482+
case vmIntrinsics::_isPrimitive : {
483+
assert(x->number_of_arguments() == 1, "wrong type");
484+
485+
// Class.isPrimitive is known on constant classes:
486+
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
487+
if (c != NULL && !c->value()->is_null_object()) {
488+
ciType* t = c->value()->java_mirror_type();
489+
set_constant(t->is_primitive_type());
490+
}
491+
break;
492+
}
482493
}
483494
}
484495

hotspot/src/share/vm/c1/c1_GraphBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3514,6 +3514,7 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
35143514

35153515
case vmIntrinsics::_getClass :
35163516
case vmIntrinsics::_isInstance :
3517+
case vmIntrinsics::_isPrimitive :
35173518
if (!InlineClassNatives) return false;
35183519
preserves_state = true;
35193520
break;

hotspot/src/share/vm/c1/c1_LIRGenerator.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,24 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
12901290
__ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
12911291
}
12921292

1293+
// java.lang.Class::isPrimitive()
1294+
void LIRGenerator::do_isPrimitive(Intrinsic* x) {
1295+
assert(x->number_of_arguments() == 1, "wrong type");
1296+
1297+
LIRItem rcvr(x->argument_at(0), this);
1298+
rcvr.load_item();
1299+
LIR_Opr temp = new_register(T_METADATA);
1300+
LIR_Opr result = rlock_result(x);
1301+
1302+
CodeEmitInfo* info = NULL;
1303+
if (x->needs_null_check()) {
1304+
info = state_for(x);
1305+
}
1306+
1307+
__ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info);
1308+
__ cmp(lir_cond_notEqual, temp, LIR_OprFact::intConst(0));
1309+
__ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN);
1310+
}
12931311

12941312
// Example: Thread.currentThread()
12951313
void LIRGenerator::do_currentThread(Intrinsic* x) {
@@ -3187,6 +3205,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
31873205

31883206
case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break;
31893207
case vmIntrinsics::_isInstance: do_isInstance(x); break;
3208+
case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break;
31903209
case vmIntrinsics::_getClass: do_getClass(x); break;
31913210
case vmIntrinsics::_currentThread: do_currentThread(x); break;
31923211

hotspot/src/share/vm/c1/c1_LIRGenerator.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
242242

243243
void do_RegisterFinalizer(Intrinsic* x);
244244
void do_isInstance(Intrinsic* x);
245+
void do_isPrimitive(Intrinsic* x);
245246
void do_getClass(Intrinsic* x);
246247
void do_currentThread(Intrinsic* x);
247248
void do_MathIntrinsic(Intrinsic* x);
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8150669
27+
* @summary C1 intrinsic for Class.isPrimitive
28+
*
29+
* @run main/othervm -ea -Diters=200 -Xint TestIsPrimitive
30+
* @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 TestIsPrimitive
31+
* @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 TestIsPrimitive
32+
*/
33+
import java.lang.reflect.Field;
34+
import java.lang.reflect.Array;
35+
import java.util.concurrent.Callable;
36+
37+
public class TestIsPrimitive {
38+
static final int ITERS = Integer.getInteger("iters", 1);
39+
40+
public static void main(String... args) throws Exception {
41+
testOK(true, InlineConstants::testBoolean);
42+
testOK(true, InlineConstants::testByte);
43+
testOK(true, InlineConstants::testShort);
44+
testOK(true, InlineConstants::testChar);
45+
testOK(true, InlineConstants::testInt);
46+
testOK(true, InlineConstants::testFloat);
47+
testOK(true, InlineConstants::testLong);
48+
testOK(true, InlineConstants::testDouble);
49+
testOK(false, InlineConstants::testObject);
50+
testOK(false, InlineConstants::testArray);
51+
52+
testOK(true, StaticConstants::testBoolean);
53+
testOK(true, StaticConstants::testByte);
54+
testOK(true, StaticConstants::testShort);
55+
testOK(true, StaticConstants::testChar);
56+
testOK(true, StaticConstants::testInt);
57+
testOK(true, StaticConstants::testFloat);
58+
testOK(true, StaticConstants::testLong);
59+
testOK(true, StaticConstants::testDouble);
60+
testOK(false, StaticConstants::testObject);
61+
testOK(false, StaticConstants::testArray);
62+
testNPE( StaticConstants::testNull);
63+
64+
testOK(true, NoConstants::testBoolean);
65+
testOK(true, NoConstants::testByte);
66+
testOK(true, NoConstants::testShort);
67+
testOK(true, NoConstants::testChar);
68+
testOK(true, NoConstants::testInt);
69+
testOK(true, NoConstants::testFloat);
70+
testOK(true, NoConstants::testLong);
71+
testOK(true, NoConstants::testDouble);
72+
testOK(false, NoConstants::testObject);
73+
testOK(false, NoConstants::testArray);
74+
testNPE( NoConstants::testNull);
75+
}
76+
77+
public static void testOK(boolean expected, Callable<Object> test) throws Exception {
78+
for (int c = 0; c < ITERS; c++) {
79+
Object res = test.call();
80+
if (!res.equals(expected)) {
81+
throw new IllegalStateException("Wrong result: expected = " + expected + ", but got " + res);
82+
}
83+
}
84+
}
85+
86+
static volatile Object sink;
87+
88+
public static void testNPE(Callable<Object> test) throws Exception {
89+
for (int c = 0; c < ITERS; c++) {
90+
try {
91+
sink = test.call();
92+
throw new IllegalStateException("Expected NPE");
93+
} catch (NullPointerException iae) {
94+
// expected
95+
}
96+
}
97+
}
98+
99+
static volatile Class<?> classBoolean = boolean.class;
100+
static volatile Class<?> classByte = byte.class;
101+
static volatile Class<?> classShort = short.class;
102+
static volatile Class<?> classChar = char.class;
103+
static volatile Class<?> classInt = int.class;
104+
static volatile Class<?> classFloat = float.class;
105+
static volatile Class<?> classLong = long.class;
106+
static volatile Class<?> classDouble = double.class;
107+
static volatile Class<?> classObject = Object.class;
108+
static volatile Class<?> classArray = Object[].class;
109+
static volatile Class<?> classNull = null;
110+
111+
static final Class<?> staticClassBoolean = boolean.class;
112+
static final Class<?> staticClassByte = byte.class;
113+
static final Class<?> staticClassShort = short.class;
114+
static final Class<?> staticClassChar = char.class;
115+
static final Class<?> staticClassInt = int.class;
116+
static final Class<?> staticClassFloat = float.class;
117+
static final Class<?> staticClassLong = long.class;
118+
static final Class<?> staticClassDouble = double.class;
119+
static final Class<?> staticClassObject = Object.class;
120+
static final Class<?> staticClassArray = Object[].class;
121+
static final Class<?> staticClassNull = null;
122+
123+
static class InlineConstants {
124+
static boolean testBoolean() { return boolean.class.isPrimitive(); }
125+
static boolean testByte() { return byte.class.isPrimitive(); }
126+
static boolean testShort() { return short.class.isPrimitive(); }
127+
static boolean testChar() { return char.class.isPrimitive(); }
128+
static boolean testInt() { return int.class.isPrimitive(); }
129+
static boolean testFloat() { return float.class.isPrimitive(); }
130+
static boolean testLong() { return long.class.isPrimitive(); }
131+
static boolean testDouble() { return double.class.isPrimitive(); }
132+
static boolean testObject() { return Object.class.isPrimitive(); }
133+
static boolean testArray() { return Object[].class.isPrimitive(); }
134+
}
135+
136+
static class StaticConstants {
137+
static boolean testBoolean() { return staticClassBoolean.isPrimitive(); }
138+
static boolean testByte() { return staticClassByte.isPrimitive(); }
139+
static boolean testShort() { return staticClassShort.isPrimitive(); }
140+
static boolean testChar() { return staticClassChar.isPrimitive(); }
141+
static boolean testInt() { return staticClassInt.isPrimitive(); }
142+
static boolean testFloat() { return staticClassFloat.isPrimitive(); }
143+
static boolean testLong() { return staticClassLong.isPrimitive(); }
144+
static boolean testDouble() { return staticClassDouble.isPrimitive(); }
145+
static boolean testObject() { return staticClassObject.isPrimitive(); }
146+
static boolean testArray() { return staticClassArray.isPrimitive(); }
147+
static boolean testNull() { return staticClassNull.isPrimitive(); }
148+
}
149+
150+
static class NoConstants {
151+
static boolean testBoolean() { return classBoolean.isPrimitive(); }
152+
static boolean testByte() { return classByte.isPrimitive(); }
153+
static boolean testShort() { return classShort.isPrimitive(); }
154+
static boolean testChar() { return classChar.isPrimitive(); }
155+
static boolean testInt() { return classInt.isPrimitive(); }
156+
static boolean testFloat() { return classFloat.isPrimitive(); }
157+
static boolean testLong() { return classLong.isPrimitive(); }
158+
static boolean testDouble() { return classDouble.isPrimitive(); }
159+
static boolean testObject() { return classObject.isPrimitive(); }
160+
static boolean testArray() { return classArray.isPrimitive(); }
161+
static boolean testNull() { return classNull.isPrimitive(); }
162+
}
163+
164+
}
165+

0 commit comments

Comments
 (0)