src/share/vm/opto/machnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/machnode.cpp	Fri Nov 12 05:56:56 2010
--- new/src/share/vm/opto/machnode.cpp	Fri Nov 12 05:56:55 2010

*** 1,7 **** --- 1,7 ---- /* ! * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. ! * Copyright (c) 1997, 2010, 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.
*** 485,494 **** --- 485,693 ---- void MachTypeNode::dump_spec(outputStream *st) const { _bottom_type->dump_on(st); } #endif + + //============================================================================= + // Two Constant's are equal when the type and the value are equal. + bool MachConstantBaseNode::Constant::operator==(const Constant& other) { + if (type() != other.type() ) return false; + if (can_be_reused() != other.can_be_reused()) return false; + // For floating point values we compare the bit pattern. + switch (type()) { + case T_FLOAT: return (_value.i == other._value.i); + case T_LONG: + case T_DOUBLE: return (_value.j == other._value.j); + case T_OBJECT: + case T_ADDRESS: return (_value.l == other._value.l); + case T_VOID: return (_value.l == other._value.l); // jump-table entries + default: ShouldNotReachHere(); + } + return false; + } + + int MachConstantBaseNode::add_constant(Constant& con) { + if (con.can_be_reused()) { + int idx = _constants.find(con); + if (idx != -1 && _constants.at(idx).can_be_reused()) { + return idx; + } + } + int idx = _constants.append(con); + return idx; + } + + // Emit constants grouped in the following order: + static BasicType type_order[] = { + T_FLOAT, // 32-bit + T_OBJECT, // 32 or 64-bit + T_ADDRESS, // 32 or 64-bit + T_DOUBLE, // 64-bit + T_LONG, // 64-bit + T_VOID, // 32 or 64-bit (jump-tables are at the end of the constant table for code emission reasons) + T_ILLEGAL + }; + + static int type_to_size_in_bytes(BasicType t) { + switch (t) { + case T_LONG: return sizeof(jlong ); + case T_FLOAT: return sizeof(jfloat ); + case T_DOUBLE: return sizeof(jdouble); + // We use T_VOID as marker for jump-table entries (labels) which + // need an interal word relocation. + case T_VOID: + case T_ADDRESS: + case T_OBJECT: return sizeof(jobject); + } + + ShouldNotReachHere(); + return -1; + } + + int MachConstantBaseNode::calculate_constant_table_size() { + int size = 0; + for (int t = 0; type_order[t] != T_ILLEGAL; t++) { + BasicType type = type_order[t]; + + for (int i = 0; i < _constants.length(); i++) { + Constant con = _constants.at(i); + if (con.type() != type) continue; // Skip other types. + + // Align size for type and add type size; + int typesize = type_to_size_in_bytes(con.type()); + size = align_size_up(size, typesize) + typesize; + } + } + + // Align up to the next section start, which is insts (see + // CodeBuffer::align_at_start). + return align_size_up(size, CodeEntryAlignment); + } + + void MachConstantBaseNode::emit_constant_table(CodeBuffer& cb) { + MacroAssembler _masm(&cb); + for (int t = 0; type_order[t] != T_ILLEGAL; t++) { + BasicType type = type_order[t]; + + for (int i = 0; i < _constants.length(); i++) { + Constant con = _constants.at(i); + if (con.type() != type) continue; // Skip other types. + + address constant_addr; + switch (con.type()) { + case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; + case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; + case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; + case T_OBJECT: { + jobject obj = con.get_jobject(); + int oop_index = _masm.oop_recorder()->find_index(obj); + constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); + break; + } + case T_ADDRESS: { + address addr = (address) con.get_jobject(); + constant_addr = _masm.address_constant(addr); + break; + } + // We use T_VOID as marker for jump-table entries (labels) which + // need an interal word relocation. + case T_VOID: { + // Write a dummy word. The real value is filled in later + // in fill_jump_table_in_constant_table. + address addr = (address) con.get_jobject(); + constant_addr = _masm.address_constant(addr); + break; + } + default: ShouldNotReachHere(); + } + assert(constant_addr != NULL, "consts section too small"); + con.set_offset(constant_addr - _masm.code()->consts()->start()); + _constants.at_put(i, con); + } + } + } + + int MachConstantBaseNode::find_constant_offset(Constant& con) const { + int idx = _constants.find(con); + assert(idx != -1, "constant must be in constant table"); + int offset = _constants.at(idx).offset(); + return offset; + } + + + //============================================================================= + void MachConstantNode::add_to_constant_table(BasicType type, jvalue value) { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + _constant = MachConstantBaseNode::Constant(type, value); + (void) base->add_constant(_constant); + } + + void MachConstantNode::add_to_constant_table(MachOper* oper) { + jvalue value; + BasicType type = oper->type()->basic_type(); + switch (type) { + case T_LONG: value.j = oper->constantL(); break; + case T_FLOAT: value.f = oper->constantF(); break; + case T_DOUBLE: value.d = oper->constantD(); break; + case T_OBJECT: + case T_ADDRESS: value.l = (jobject) oper->constant(); break; + default: ShouldNotReachHere(); + } + add_to_constant_table(type, value); + } + + void MachConstantNode::allocate_jump_table_in_constant_table() { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + jvalue value; + // We can use the 'this' pointer here to identify the right jump-table + // as this method is called from Compile::Fill_buffer right before + // the MachNodes are emitted and the table is filled (means the + // MachNode pointers do not change anymore). + value.l = (jobject) this; + _constant = MachConstantBaseNode::Constant(T_VOID, value, false); // Labels of a jump-table cannot be reused. + for (uint i = 0; i < outcnt(); i++) { + (void) base->add_constant(_constant); + } + } + + void MachConstantNode::fill_jump_table_in_constant_table(CodeBuffer& cb, GrowableArray<Label*> labels) const { + // If called from Compile::scratch_emit_size do nothing. + if (Compile::current()->in_scratch_emit_size()) return; + + assert(labels.is_nonempty(), "must be"); + assert((uint) labels.length() == outcnt(), err_msg("must be equal: %d == %d", labels.length(), outcnt())); + + // Since constant_offset() also contains table_base_offset() we need + // to subtract the table_base_offset() to get the plain offset into + // the constant table. + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + int offset = constant_offset() - base->table_base_offset(); + + MacroAssembler _masm(&cb); + address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset); + + for (int i = 0; i < labels.length(); i++) { + address* constant_addr = &jump_table_base[i]; + assert(*constant_addr == (address) this, "all jump-table entries must contain 'this' value"); + *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr); + cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type); + } + } + + int MachConstantNode::constant_offset() { + int offset = _constant.offset(); + // Bind the offset lazily. + if (offset == -1) { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + offset = base->table_base_offset() + base->find_constant_offset(_constant); + _constant.set_offset(offset); + } + return offset; + } + + //============================================================================= #ifndef PRODUCT void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { int reg = ra_->get_reg_first(in(1)->in(_vidx)); tty->print("%s %s", Name(), Matcher::regName[reg]);

src/share/vm/opto/machnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File