Path: blob/master/src/hotspot/share/opto/constantTable.cpp
40930 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "asm/codeBuffer.hpp"26#include "asm/macroAssembler.hpp"27#include "opto/block.hpp"28#include "opto/constantTable.hpp"29#include "opto/machnode.hpp"30#include "opto/output.hpp"3132//=============================================================================33// Two Constant's are equal when the type and the value are equal.34bool ConstantTable::Constant::operator==(const Constant& other) {35if (type() != other.type() ) return false;36if (can_be_reused() != other.can_be_reused()) return false;37// For floating point values we compare the bit pattern.38switch (type()) {39case T_INT:40case T_FLOAT: return (_v._value.i == other._v._value.i);41case T_LONG:42case T_DOUBLE: return (_v._value.j == other._v._value.j);43case T_OBJECT:44case T_ADDRESS: return (_v._value.l == other._v._value.l);45case T_VOID: return (_v._value.l == other._v._value.l); // jump-table entries46case T_METADATA: return (_v._metadata == other._v._metadata);47default: ShouldNotReachHere(); return false;48}49}5051int ConstantTable::qsort_comparator(Constant* a, Constant* b) {52// sort descending53if (a->freq() > b->freq()) return -1;54if (a->freq() < b->freq()) return 1;55return 0;56}5758static int type_to_size_in_bytes(BasicType t) {59switch (t) {60case T_INT: return sizeof(jint );61case T_LONG: return sizeof(jlong );62case T_FLOAT: return sizeof(jfloat );63case T_DOUBLE: return sizeof(jdouble);64case T_METADATA: return sizeof(Metadata*);65// We use T_VOID as marker for jump-table entries (labels) which66// need an internal word relocation.67case T_VOID:68case T_ADDRESS:69case T_OBJECT: return sizeof(jobject);70default:71ShouldNotReachHere();72return -1;73}74}7576void ConstantTable::calculate_offsets_and_size() {77// First, sort the array by frequencies.78_constants.sort(qsort_comparator);7980#ifdef ASSERT81// Make sure all jump-table entries were sorted to the end of the82// array (they have a negative frequency).83bool found_void = false;84for (int i = 0; i < _constants.length(); i++) {85Constant con = _constants.at(i);86if (con.type() == T_VOID)87found_void = true; // jump-tables88else89assert(!found_void, "wrong sorting");90}91#endif9293int offset = 0;94for (int i = 0; i < _constants.length(); i++) {95Constant* con = _constants.adr_at(i);9697// Align offset for type.98int typesize = type_to_size_in_bytes(con->type());99offset = align_up(offset, typesize);100con->set_offset(offset); // set constant's offset101102if (con->type() == T_VOID) {103MachConstantNode* n = (MachConstantNode*) con->get_jobject();104offset = offset + typesize * n->outcnt(); // expand jump-table105} else {106offset = offset + typesize;107}108}109110// Align size up to the next section start (which is insts; see111// CodeBuffer::align_at_start).112assert(_size == -1, "already set?");113_size = align_up(offset, (int)CodeEntryAlignment);114}115116bool ConstantTable::emit(CodeBuffer& cb) const {117MacroAssembler _masm(&cb);118for (int i = 0; i < _constants.length(); i++) {119Constant con = _constants.at(i);120address constant_addr = NULL;121switch (con.type()) {122case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break;123case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;124case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break;125case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;126case T_OBJECT: {127jobject obj = con.get_jobject();128int oop_index = _masm.oop_recorder()->find_index(obj);129constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));130break;131}132case T_ADDRESS: {133address addr = (address) con.get_jobject();134constant_addr = _masm.address_constant(addr);135break;136}137// We use T_VOID as marker for jump-table entries (labels) which138// need an internal word relocation.139case T_VOID: {140MachConstantNode* n = (MachConstantNode*) con.get_jobject();141// Fill the jump-table with a dummy word. The real value is142// filled in later in fill_jump_table.143address dummy = (address) n;144constant_addr = _masm.address_constant(dummy);145if (constant_addr == NULL) {146return false;147}148assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),149"must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));150151// Expand jump-table152address last_addr = NULL;153for (uint j = 1; j < n->outcnt(); j++) {154last_addr = _masm.address_constant(dummy + j);155if (last_addr == NULL) {156return false;157}158}159#ifdef ASSERT160address start = _masm.code()->consts()->start();161address new_constant_addr = last_addr - ((n->outcnt() - 1) * sizeof(address));162// Expanding the jump-table could result in an expansion of the const code section.163// In that case, we need to check if the new constant address matches the offset.164assert((constant_addr - start == con.offset()) || (new_constant_addr - start == con.offset()),165"must be: %d == %d or %d == %d (after an expansion)", (int)(constant_addr - start), (int)(con.offset()),166(int)(new_constant_addr - start), (int)(con.offset()));167#endif168continue; // Loop169}170case T_METADATA: {171Metadata* obj = con.get_metadata();172int metadata_index = _masm.oop_recorder()->find_index(obj);173constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index));174break;175}176default: ShouldNotReachHere();177}178179if (constant_addr == NULL) {180return false;181}182assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),183"must be: %d == %d", (int)(constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));184}185return true;186}187188int ConstantTable::find_offset(Constant& con) const {189int idx = _constants.find(con);190guarantee(idx != -1, "constant must be in constant table");191int offset = _constants.at(idx).offset();192guarantee(offset != -1, "constant table not emitted yet?");193return offset;194}195196void ConstantTable::add(Constant& con) {197if (con.can_be_reused()) {198int idx = _constants.find(con);199if (idx != -1 && _constants.at(idx).can_be_reused()) {200_constants.adr_at(idx)->inc_freq(con.freq()); // increase the frequency by the current value201return;202}203}204(void) _constants.append(con);205}206207ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {208Block* b = Compile::current()->cfg()->get_block_for_node(n);209Constant con(type, value, b->_freq);210add(con);211return con;212}213214ConstantTable::Constant ConstantTable::add(Metadata* metadata) {215Constant con(metadata);216add(con);217return con;218}219220ConstantTable::Constant ConstantTable::add(MachConstantNode* n, MachOper* oper) {221jvalue value;222BasicType type = oper->type()->basic_type();223switch (type) {224case T_LONG: value.j = oper->constantL(); break;225case T_FLOAT: value.f = oper->constantF(); break;226case T_DOUBLE: value.d = oper->constantD(); break;227case T_OBJECT:228case T_ADDRESS: value.l = (jobject) oper->constant(); break;229case T_METADATA: return add((Metadata*)oper->constant()); break;230default: guarantee(false, "unhandled type: %s", type2name(type));231}232return add(n, type, value);233}234235ConstantTable::Constant ConstantTable::add_jump_table(MachConstantNode* n) {236jvalue value;237// We can use the node pointer here to identify the right jump-table238// as this method is called from Compile::Fill_buffer right before239// the MachNodes are emitted and the jump-table is filled (means the240// MachNode pointers do not change anymore).241value.l = (jobject) n;242Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused.243add(con);244return con;245}246247void ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {248// If called from Compile::scratch_emit_size do nothing.249if (Compile::current()->output()->in_scratch_emit_size()) return;250251assert(labels.is_nonempty(), "must be");252assert((uint) labels.length() == n->outcnt(), "must be equal: %d == %d", labels.length(), n->outcnt());253254// Since MachConstantNode::constant_offset() also contains255// table_base_offset() we need to subtract the table_base_offset()256// to get the plain offset into the constant table.257int offset = n->constant_offset() - table_base_offset();258259MacroAssembler _masm(&cb);260address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);261262for (uint i = 0; i < n->outcnt(); i++) {263address* constant_addr = &jump_table_base[i];264assert(*constant_addr == (((address) n) + i), "all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, p2i(*constant_addr), p2i(((address) n) + i));265*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);266cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);267}268}269270271