mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-23 03:48:13 +00:00
8150669: C1 intrinsic for Class.isPrimitive
Reviewed-by: twisti, vlivanov, redestad
This commit is contained in:
parent
c40e7bc21f
commit
890f94d7e6
@ -471,7 +471,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
|
||||
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
|
||||
if (c != NULL && !c->value()->is_null_object()) {
|
||||
// ciInstance::java_mirror_type() returns non-NULL only for Java mirrors
|
||||
ciType* t = c->value()->as_instance()->java_mirror_type();
|
||||
ciType* t = c->value()->java_mirror_type();
|
||||
if (t->is_klass()) {
|
||||
// substitute cls.isInstance(obj) of a constant Class into
|
||||
// an InstantOf instruction
|
||||
@ -487,6 +487,17 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case vmIntrinsics::_isPrimitive : {
|
||||
assert(x->number_of_arguments() == 1, "wrong type");
|
||||
|
||||
// Class.isPrimitive is known on constant classes:
|
||||
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
|
||||
if (c != NULL && !c->value()->is_null_object()) {
|
||||
ciType* t = c->value()->java_mirror_type();
|
||||
set_constant(t->is_primitive_type());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -148,6 +148,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
|
||||
case vmIntrinsics::_longBitsToDouble:
|
||||
case vmIntrinsics::_getClass:
|
||||
case vmIntrinsics::_isInstance:
|
||||
case vmIntrinsics::_isPrimitive:
|
||||
case vmIntrinsics::_currentThread:
|
||||
case vmIntrinsics::_dabs:
|
||||
case vmIntrinsics::_dsqrt:
|
||||
|
||||
@ -1293,6 +1293,25 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
|
||||
__ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
|
||||
}
|
||||
|
||||
// java.lang.Class::isPrimitive()
|
||||
void LIRGenerator::do_isPrimitive(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 1, "wrong type");
|
||||
|
||||
LIRItem rcvr(x->argument_at(0), this);
|
||||
rcvr.load_item();
|
||||
LIR_Opr temp = new_register(T_METADATA);
|
||||
LIR_Opr result = rlock_result(x);
|
||||
|
||||
CodeEmitInfo* info = NULL;
|
||||
if (x->needs_null_check()) {
|
||||
info = state_for(x);
|
||||
}
|
||||
|
||||
__ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info);
|
||||
__ cmp(lir_cond_notEqual, temp, LIR_OprFact::intConst(0));
|
||||
__ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
// Example: Thread.currentThread()
|
||||
void LIRGenerator::do_currentThread(Intrinsic* x) {
|
||||
@ -3132,6 +3151,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
|
||||
|
||||
case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break;
|
||||
case vmIntrinsics::_isInstance: do_isInstance(x); break;
|
||||
case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break;
|
||||
case vmIntrinsics::_getClass: do_getClass(x); break;
|
||||
case vmIntrinsics::_currentThread: do_currentThread(x); break;
|
||||
|
||||
|
||||
@ -246,6 +246,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
|
||||
void do_RegisterFinalizer(Intrinsic* x);
|
||||
void do_isInstance(Intrinsic* x);
|
||||
void do_isPrimitive(Intrinsic* x);
|
||||
void do_getClass(Intrinsic* x);
|
||||
void do_currentThread(Intrinsic* x);
|
||||
void do_MathIntrinsic(Intrinsic* x);
|
||||
|
||||
166
hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java
Normal file
166
hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8150669
|
||||
* @summary C1 intrinsic for Class.isPrimitive
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @run main/othervm -ea -Diters=200 -Xint TestClassIsPrimitive
|
||||
* @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 TestClassIsPrimitive
|
||||
* @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 TestClassIsPrimitive
|
||||
*/
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class TestClassIsPrimitive {
|
||||
static final int ITERS = Integer.getInteger("iters", 1);
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
testOK(true, InlineConstants::testBoolean);
|
||||
testOK(true, InlineConstants::testByte);
|
||||
testOK(true, InlineConstants::testShort);
|
||||
testOK(true, InlineConstants::testChar);
|
||||
testOK(true, InlineConstants::testInt);
|
||||
testOK(true, InlineConstants::testFloat);
|
||||
testOK(true, InlineConstants::testLong);
|
||||
testOK(true, InlineConstants::testDouble);
|
||||
testOK(false, InlineConstants::testObject);
|
||||
testOK(false, InlineConstants::testArray);
|
||||
|
||||
testOK(true, StaticConstants::testBoolean);
|
||||
testOK(true, StaticConstants::testByte);
|
||||
testOK(true, StaticConstants::testShort);
|
||||
testOK(true, StaticConstants::testChar);
|
||||
testOK(true, StaticConstants::testInt);
|
||||
testOK(true, StaticConstants::testFloat);
|
||||
testOK(true, StaticConstants::testLong);
|
||||
testOK(true, StaticConstants::testDouble);
|
||||
testOK(false, StaticConstants::testObject);
|
||||
testOK(false, StaticConstants::testArray);
|
||||
testNPE( StaticConstants::testNull);
|
||||
|
||||
testOK(true, NoConstants::testBoolean);
|
||||
testOK(true, NoConstants::testByte);
|
||||
testOK(true, NoConstants::testShort);
|
||||
testOK(true, NoConstants::testChar);
|
||||
testOK(true, NoConstants::testInt);
|
||||
testOK(true, NoConstants::testFloat);
|
||||
testOK(true, NoConstants::testLong);
|
||||
testOK(true, NoConstants::testDouble);
|
||||
testOK(false, NoConstants::testObject);
|
||||
testOK(false, NoConstants::testArray);
|
||||
testNPE( NoConstants::testNull);
|
||||
}
|
||||
|
||||
public static void testOK(boolean expected, Callable<Object> test) throws Exception {
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
Object res = test.call();
|
||||
if (!res.equals(expected)) {
|
||||
throw new IllegalStateException("Wrong result: expected = " + expected + ", but got " + res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static volatile Object sink;
|
||||
|
||||
public static void testNPE(Callable<Object> test) throws Exception {
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
try {
|
||||
sink = test.call();
|
||||
throw new IllegalStateException("Expected NPE");
|
||||
} catch (NullPointerException iae) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static volatile Class<?> classBoolean = boolean.class;
|
||||
static volatile Class<?> classByte = byte.class;
|
||||
static volatile Class<?> classShort = short.class;
|
||||
static volatile Class<?> classChar = char.class;
|
||||
static volatile Class<?> classInt = int.class;
|
||||
static volatile Class<?> classFloat = float.class;
|
||||
static volatile Class<?> classLong = long.class;
|
||||
static volatile Class<?> classDouble = double.class;
|
||||
static volatile Class<?> classObject = Object.class;
|
||||
static volatile Class<?> classArray = Object[].class;
|
||||
static volatile Class<?> classNull = null;
|
||||
|
||||
static final Class<?> staticClassBoolean = boolean.class;
|
||||
static final Class<?> staticClassByte = byte.class;
|
||||
static final Class<?> staticClassShort = short.class;
|
||||
static final Class<?> staticClassChar = char.class;
|
||||
static final Class<?> staticClassInt = int.class;
|
||||
static final Class<?> staticClassFloat = float.class;
|
||||
static final Class<?> staticClassLong = long.class;
|
||||
static final Class<?> staticClassDouble = double.class;
|
||||
static final Class<?> staticClassObject = Object.class;
|
||||
static final Class<?> staticClassArray = Object[].class;
|
||||
static final Class<?> staticClassNull = null;
|
||||
|
||||
static class InlineConstants {
|
||||
static boolean testBoolean() { return boolean.class.isPrimitive(); }
|
||||
static boolean testByte() { return byte.class.isPrimitive(); }
|
||||
static boolean testShort() { return short.class.isPrimitive(); }
|
||||
static boolean testChar() { return char.class.isPrimitive(); }
|
||||
static boolean testInt() { return int.class.isPrimitive(); }
|
||||
static boolean testFloat() { return float.class.isPrimitive(); }
|
||||
static boolean testLong() { return long.class.isPrimitive(); }
|
||||
static boolean testDouble() { return double.class.isPrimitive(); }
|
||||
static boolean testObject() { return Object.class.isPrimitive(); }
|
||||
static boolean testArray() { return Object[].class.isPrimitive(); }
|
||||
}
|
||||
|
||||
static class StaticConstants {
|
||||
static boolean testBoolean() { return staticClassBoolean.isPrimitive(); }
|
||||
static boolean testByte() { return staticClassByte.isPrimitive(); }
|
||||
static boolean testShort() { return staticClassShort.isPrimitive(); }
|
||||
static boolean testChar() { return staticClassChar.isPrimitive(); }
|
||||
static boolean testInt() { return staticClassInt.isPrimitive(); }
|
||||
static boolean testFloat() { return staticClassFloat.isPrimitive(); }
|
||||
static boolean testLong() { return staticClassLong.isPrimitive(); }
|
||||
static boolean testDouble() { return staticClassDouble.isPrimitive(); }
|
||||
static boolean testObject() { return staticClassObject.isPrimitive(); }
|
||||
static boolean testArray() { return staticClassArray.isPrimitive(); }
|
||||
static boolean testNull() { return staticClassNull.isPrimitive(); }
|
||||
}
|
||||
|
||||
static class NoConstants {
|
||||
static boolean testBoolean() { return classBoolean.isPrimitive(); }
|
||||
static boolean testByte() { return classByte.isPrimitive(); }
|
||||
static boolean testShort() { return classShort.isPrimitive(); }
|
||||
static boolean testChar() { return classChar.isPrimitive(); }
|
||||
static boolean testInt() { return classInt.isPrimitive(); }
|
||||
static boolean testFloat() { return classFloat.isPrimitive(); }
|
||||
static boolean testLong() { return classLong.isPrimitive(); }
|
||||
static boolean testDouble() { return classDouble.isPrimitive(); }
|
||||
static boolean testObject() { return classObject.isPrimitive(); }
|
||||
static boolean testArray() { return classArray.isPrimitive(); }
|
||||
static boolean testNull() { return classNull.isPrimitive(); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user