Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8265711: C1: Intrinsify Class.getModifier method #3616

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
@@ -548,6 +548,22 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
}
break;
}
case vmIntrinsics::_getModifiers: {
assert(x->number_of_arguments() == 1, "wrong type");

// Optimize for Foo.class.getModifier()
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
if (c != NULL && !c->value()->is_null_object()) {
ciType* t = c->value()->java_mirror_type();
if (t->is_klass()) {

This comment has been minimized.

Loading
@TobiHartmann

TobiHartmann Apr 26, 2021
Member

Shouldn't t->is_primitive_type() be handled as well?

This comment has been minimized.

Loading
@kelthuzadx

kelthuzadx Apr 27, 2021
Author Member

Done.

Testing:

  • hotspot/jtreg/compiler
set_constant(t->as_klass()->modifier_flags());
} else {
assert(t->is_primitive_type(), "should be a primitive type");
set_constant(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
}
}
break;
}
default:
break;
}
@@ -150,6 +150,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_getClass:
case vmIntrinsics::_isInstance:
case vmIntrinsics::_isPrimitive:
case vmIntrinsics::_getModifiers:
case vmIntrinsics::_currentThread:
case vmIntrinsics::_dabs:
case vmIntrinsics::_dsqrt:
@@ -1311,6 +1311,34 @@ void LIRGenerator::do_isPrimitive(Intrinsic* x) {
__ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN);
}

// Example: Foo.class.getModifiers()
void LIRGenerator::do_getModifiers(Intrinsic* x) {
assert(x->number_of_arguments() == 1, "wrong type");

LIRItem receiver(x->argument_at(0), this);
receiver.load_item();
LIR_Opr result = rlock_result(x);

CodeEmitInfo* info = NULL;
if (x->needs_null_check()) {
info = state_for(x);
}

LabelObj* L_not_prim = new LabelObj();
LabelObj* L_done = new LabelObj();

LIR_Opr klass = new_register(T_METADATA);
// Checking if it's a java mirror of primitive type
__ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), klass, info);
__ cmp(lir_cond_notEqual, klass, LIR_OprFact::metadataConst(0));
__ branch(lir_cond_notEqual, L_not_prim->label());
__ move(LIR_OprFact::intConst(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC), result);
__ branch(lir_cond_always, L_done->label());

__ branch_destination(L_not_prim->label());
__ move(new LIR_Address(klass, in_bytes(Klass::modifier_flags_offset()), T_INT), result);
__ branch_destination(L_done->label());
}

// Example: Thread.currentThread()
void LIRGenerator::do_currentThread(Intrinsic* x) {
@@ -3140,6 +3168,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::_getModifiers: do_getModifiers(x); break;
case vmIntrinsics::_getClass: do_getClass(x); break;
case vmIntrinsics::_currentThread: do_currentThread(x); break;
case vmIntrinsics::_getObjectSize: do_getObjectSize(x); break;
@@ -251,6 +251,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_RegisterFinalizer(Intrinsic* x);
void do_isInstance(Intrinsic* x);
void do_isPrimitive(Intrinsic* x);
void do_getModifiers(Intrinsic* x);
void do_getClass(Intrinsic* x);
void do_currentThread(Intrinsic* x);
void do_getObjectSize(Intrinsic* x);
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2021, Alibaba Group Holding Limited. 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
* @author Yi Yang
* @summary Canonicalizes Foo.class.getModifiers() with interpreter mode
* @library /test/lib
* @run main/othervm -Xint
* -XX:CompileCommand=compileonly,*CanonicalizeGetModifiers.test
* compiler.c1.CanonicalizeGetModifiers
*/

/*
* @test
* @author Yi Yang
* @summary Canonicalizes Foo.class.getModifiers() with C1 mode
* @requires vm.compiler1.enabled
* @library /test/lib
* @run main/othervm -XX:TieredStopAtLevel=1 -XX:+TieredCompilation
* -XX:CompileCommand=compileonly,*CanonicalizeGetModifiers.test
* compiler.c1.CanonicalizeGetModifiers
*/

/*
* @test
* @author Yi Yang
* @summary Canonicalizes Foo.class.getModifiers() with C2 mode
* @requires vm.compiler2.enabled
* @library /test/lib
* @run main/othervm -XX:-TieredCompilation
* -XX:CompileCommand=compileonly,*CanonicalizeGetModifiers.test
* compiler.c1.CanonicalizeGetModifiers
*/

package compiler.c1;

import java.lang.reflect.Modifier;

import jdk.test.lib.Asserts;

public class CanonicalizeGetModifiers {
public static class T1 {
}

public static final class T2 {
}

private static class T3 {
}

protected static class T4 {
}

class T5 {
}

interface T6 {
}

static void test(Class poison) {
Asserts.assertEQ(CanonicalizeGetModifiers.class.getModifiers(), Modifier.PUBLIC);
Asserts.assertEQ(T1.class.getModifiers(), Modifier.PUBLIC | Modifier.STATIC);
Asserts.assertEQ(T2.class.getModifiers(), Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC);
Asserts.assertEQ(T3.class.getModifiers(), Modifier.PRIVATE | Modifier.STATIC);
Asserts.assertEQ(T4.class.getModifiers(), Modifier.PROTECTED | Modifier.STATIC);
Asserts.assertEQ(new CanonicalizeGetModifiers().new T5().getClass().getModifiers(), 0/* NONE */);
Asserts.assertEQ(T6.class.getModifiers(), Modifier.ABSTRACT | Modifier.STATIC | Modifier.INTERFACE);

Asserts.assertEQ(int.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(long.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(double.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(float.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(char.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(byte.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(short.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(void.class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(int[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(long[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(double[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(float[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(char[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(byte[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(short[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(Object[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);
Asserts.assertEQ(CanonicalizeGetModifiers[].class.getModifiers(), Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL);

Asserts.assertEQ(new CanonicalizeGetModifiers().getClass().getModifiers(), Modifier.PUBLIC);
Asserts.assertEQ(new T1().getClass().getModifiers(), Modifier.PUBLIC | Modifier.STATIC);
Asserts.assertEQ(new T2().getClass().getModifiers(), Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC);
Asserts.assertEQ(new T3().getClass().getModifiers(), Modifier.PRIVATE | Modifier.STATIC);
Asserts.assertEQ(new T4().getClass().getModifiers(), Modifier.PROTECTED | Modifier.STATIC);
try {
// null_check
poison.getModifiers();
} catch(NullPointerException npe) {
// got it!
}
}

public static void main(String... args) {
for (int i = 0; i < 10_000; i++) {
test(i == 9999 ? null : CanonicalizeGetModifiers.class);
}
}
}