# HG changeset patch # User wangxue # Date 1531462452 -28800 # Node ID 1336d592e5b895ad4d981331739726533652bf5f # Parent 7aec3140c7b6b2190df0b60bf26a25a09464e9dc #7277 Implement LIR_Assembler::emit_profile_type for MIPS Reviewed-by: fujie, aoqi diff -r 7aec3140c7b6 -r 1336d592e5b8 src/cpu/mips/vm/c1_LIRAssembler_mips.cpp --- a/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp Thu Jul 12 15:30:06 2018 +0800 +++ b/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp Fri Jul 13 14:14:12 2018 +0800 @@ -1,6 +1,6 @@ /* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. + * Copyright (c) 2015, 2018, Loongson Technology. 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 @@ -5746,8 +5746,344 @@ } void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { - // Newly added in OpenJDK 8 - Unimplemented(); + Register obj = op->obj()->as_register(); + Register tmp = op->tmp()->as_pointer_register(); + Register tmp1 = T1; + Address mdo_addr = as_Address(op->mdp()->as_address_ptr()); + ciKlass* exact_klass = op->exact_klass(); + intptr_t current_klass = op->current_klass(); + bool not_null = op->not_null(); + bool no_conflict = op->no_conflict(); + + Label update, next, none; + + bool do_null = !not_null; + bool exact_klass_set = exact_klass != NULL && ciTypeEntries::valid_ciklass(current_klass) == exact_klass; + bool do_update = !TypeEntries::is_type_unknown(current_klass) && !exact_klass_set; + + assert(do_null || do_update, "why are we here?"); + assert(!TypeEntries::was_null_seen(current_klass) || do_update, "why are we here?"); + + __ verify_oop(obj); + + if (tmp != obj) { + __ move(tmp, obj); + } + if (do_null) { + __ bne(tmp, R0, update); + __ delayed()->nop(); + if (!TypeEntries::was_null_seen(current_klass)) { + __ push(tmp1); + if (mdo_addr.index() == noreg) { + __ ld(tmp1, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp1, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::null_seen); + __ orr(AT, tmp1, AT); + if (mdo_addr.index() == noreg) { + __ sd(AT, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(tmp1, mdo_addr.index(), mdo_addr.scale()); + __ daddu(tmp1, tmp1, mdo_addr.base()); + __ sd(AT, tmp1, mdo_addr.disp()); + } + __ pop(tmp1); + + } + if (do_update) { +#ifndef ASSERT + __ b(next); + __ delayed()->nop(); + } +#else + __ b(next); + __ delayed()->nop(); + } + } else { + __ bne(tmp, R0, update); + __ delayed()->nop(); + __ stop("unexpect null obj"); +#endif + } + + __ bind(update); + + if (do_update) { +#ifdef ASSERT + if (exact_klass != NULL) { + Label ok; + __ load_klass(tmp, tmp); + __ push(tmp); + __ mov_metadata(tmp, exact_klass->constant_encoding()); + __ ld(AT, Address(SP, 0)); + __ beq(tmp, AT, ok); + __ delayed()->nop(); + __ stop("exact klass and actual klass differ"); + __ bind(ok); + __ pop(tmp); + } +#endif + if (!no_conflict) { + if (exact_klass == NULL || TypeEntries::is_type_none(current_klass)) { + if (exact_klass != NULL) { + __ mov_metadata(tmp, exact_klass->constant_encoding()); + } else { + __ load_klass(tmp, tmp); + } + + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ xorr(tmp, tmp, AT); + __ li(AT, TypeEntries::type_klass_mask); + __ andr(AT, tmp, AT); + // klass seen before, nothing to do. The unknown bit may have been + // set already but no need to check. + __ beq(AT, R0, next); + __ delayed()->nop(); + + __ li(AT, TypeEntries::type_unknown); + __ andr(AT, tmp, AT); + __ bne(AT, R0, next); // already unknown. Nothing to do anymore. + __ delayed()->nop(); + + if (TypeEntries::is_type_none(current_klass)) { + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ beq(AT, R0, none); + __ delayed()->nop(); + + __ push(tmp1); + if (mdo_addr.index() == noreg) { + __ ld(tmp1, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp1, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::null_seen); + __ subu(AT, AT, tmp1); + __ pop(tmp1); + __ beq(AT, R0, none); + __ delayed()->nop(); + // There is a chance that the checks above (re-reading profiling + // data from memory) fail if another thread has just set the + // profiling to this obj's klass + + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ xorr(tmp, tmp, AT); + __ li(AT, TypeEntries::type_klass_mask); + __ andr(AT, tmp, AT); + __ beq(AT, R0, next); + __ delayed()->nop(); + } + } else { + assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); + if (mdo_addr.index() == noreg) { + __ ld(tmp, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::type_unknown); + __ andr(AT, tmp, AT); + __ bne(AT, R0, next); // already unknown. Nothing to do anymore. + __ delayed()->nop(); + } + + // different than before. Cannot keep accurate profile. + __ push(tmp1); + if (mdo_addr.index() == noreg) { + __ ld(tmp1, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp1, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::type_unknown); + __ orr(AT, tmp1, AT); + if (mdo_addr.index() == noreg) { + __ sd(AT, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(tmp1, mdo_addr.index(), mdo_addr.scale()); + __ daddu(tmp1, tmp1, mdo_addr.base()); + __ sd(AT, tmp1, mdo_addr.disp()); + } + __ pop(tmp1); + + if (TypeEntries::is_type_none(current_klass)) { + __ b(next); + __ delayed()->nop(); + + __ bind(none); + // first time here. Set profile type. + if (mdo_addr.index() == noreg) { + __ sd(tmp, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ sd(tmp, AT, mdo_addr.disp()); + } + } + } else { + // There's a single possible klass at this profile point + assert(exact_klass != NULL, "should be"); + if (TypeEntries::is_type_none(current_klass)) { + __ mov_metadata(tmp, exact_klass->constant_encoding()); + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ xorr(tmp, tmp, AT); + __ li(AT, TypeEntries::type_klass_mask); + __ andr(AT, tmp, AT); +#ifdef ASSERT + __ beq_far(AT, R0, next); + __ delayed()->nop(); + + { + Label ok; + __ push(tmp); + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ beq_far(AT, R0, ok); + __ delayed()->nop(); + + __ push(tmp1); + if (mdo_addr.index() == noreg) { + __ ld(tmp1, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp1, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::null_seen); + __ subu(AT, AT, tmp1); + __ pop(tmp1); + __ beq_far(AT, R0, ok); + __ delayed()->nop(); + // may have been set by another thread + __ mov_metadata(tmp, exact_klass->constant_encoding()); + if (mdo_addr.index() == noreg) { + __ ld(AT, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(AT, AT, mdo_addr.disp()); + } + __ xorr(tmp, tmp, AT); + __ li(AT, TypeEntries::type_mask); + __ andr(AT, tmp, AT); + __ beq_far(AT, R0, ok); + __ delayed()->nop(); + + __ stop("unexpected profiling mismatch"); + __ bind(ok); + __ pop(tmp); + } +#else + __ beq(AT, R0, next); + __ delayed()->nop(); +#endif + // first time here. Set profile type. + if (mdo_addr.index() == noreg) { + __ sd(tmp, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ sd(tmp, AT, mdo_addr.disp()); + } + } else { + assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); + + if (mdo_addr.index() == noreg) { + __ ld(tmp, mdo_addr); + } else { + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::type_unknown); + __ andr(AT, tmp, AT); + __ bne(AT, R0, next); // already unknown. Nothing to do anymore. + __ delayed()->nop(); + + __ push(tmp1); + if (mdo_addr.index() == noreg) { + __ ld(tmp1, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(AT, mdo_addr.index(), mdo_addr.scale()); + __ daddu(AT, AT, mdo_addr.base()); + __ ld(tmp1, AT, mdo_addr.disp()); + } + __ li(AT, TypeEntries::type_unknown); + __ orr(AT, tmp1, AT); + if (mdo_addr.index() == noreg) { + __ sd(AT, mdo_addr); + } else { + guarantee(tmp1 != mdo_addr.base(), "The base register will be corrupted !"); + guarantee(tmp1 != mdo_addr.index(), "The index register will be corrupted !"); + + __ dsll(tmp1, mdo_addr.index(), mdo_addr.scale()); + __ daddu(tmp1, tmp1, mdo_addr.base()); + __ sd(AT, tmp1, mdo_addr.disp()); + } + __ pop(tmp1); + } + } + + __ bind(next); + } } void LIR_Assembler::emit_delay(LIR_OpDelay*) { diff -r 7aec3140c7b6 -r 1336d592e5b8 src/share/vm/c1/c1_LIR.cpp --- a/src/share/vm/c1/c1_LIR.cpp Thu Jul 12 15:30:06 2018 +0800 +++ b/src/share/vm/c1/c1_LIR.cpp Fri Jul 13 14:14:12 2018 +0800 @@ -23,8 +23,8 @@ */ /* - * This file has been modified by Loongson Technology in 2015. These - * modifications are Copyright (c) 2015 Loongson Technology, and are made + * This file has been modified by Loongson Technology in 2015, 2018. These + * modifications are Copyright (c) 2015, 2018 Loongson Technology, and are made * available on the same license terms set forth above. */ @@ -2348,7 +2348,12 @@ // LIR_OpProfileType void LIR_OpProfileType::print_instr(outputStream* out) const { - out->print("exact = "); exact_klass()->print_name_on(out); + out->print("exact = "); + if (exact_klass() == NULL) { + out->print("unknown"); + } else { + exact_klass()->print_name_on(out); + } out->print("current = "); ciTypeEntries::print_ciklass(out, current_klass()); mdp()->print(out); out->print(" "); obj()->print(out); out->print(" ");