diff options
author | coleenp <none@none> | 2012-09-01 13:25:18 -0400 |
---|---|---|
committer | coleenp <none@none> | 2012-09-01 13:25:18 -0400 |
commit | c4f2a125e3006c1715c12ec6ec682389b24d7cac (patch) | |
tree | 00340ce50c7adf1b8db7e987946c2c9d747f37a3 /src/share/vm/opto | |
parent | ab8cad1d47e8e46e6e633ee5eb4cb0cdb7a0e7bb (diff) |
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
--HG--
rename : src/cpu/sparc/vm/dump_sparc.cpp => src/cpu/sparc/vm/metaspaceShared_sparc.cpp
rename : src/cpu/x86/vm/dump_x86_32.cpp => src/cpu/x86/vm/metaspaceShared_x86_32.cpp
rename : src/cpu/x86/vm/dump_x86_64.cpp => src/cpu/x86/vm/metaspaceShared_x86_64.cpp
rename : src/cpu/zero/vm/dump_zero.cpp => src/cpu/zero/vm/metaspaceShared_zero.cpp
rename : src/share/vm/oops/compiledICHolderOop.cpp => src/share/vm/oops/compiledICHolder.cpp
rename : src/share/vm/oops/compiledICHolderOop.hpp => src/share/vm/oops/compiledICHolder.hpp
rename : src/share/vm/oops/constMethodOop.cpp => src/share/vm/oops/constMethod.cpp
rename : src/share/vm/oops/constMethodOop.hpp => src/share/vm/oops/constMethod.hpp
rename : src/share/vm/oops/constantPoolOop.cpp => src/share/vm/oops/constantPool.cpp
rename : src/share/vm/oops/constantPoolOop.hpp => src/share/vm/oops/constantPool.hpp
rename : src/share/vm/oops/cpCacheOop.cpp => src/share/vm/oops/cpCache.cpp
rename : src/share/vm/oops/cpCacheOop.hpp => src/share/vm/oops/cpCache.hpp
rename : src/share/vm/oops/methodOop.cpp => src/share/vm/oops/method.cpp
rename : src/share/vm/oops/methodOop.hpp => src/share/vm/oops/method.hpp
rename : src/share/vm/oops/methodDataOop.cpp => src/share/vm/oops/methodData.cpp
rename : src/share/vm/oops/methodDataOop.hpp => src/share/vm/oops/methodData.hpp
Diffstat (limited to 'src/share/vm/opto')
29 files changed, 593 insertions, 369 deletions
diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp index 0935f5f3e..1c7b9ffee 100644 --- a/src/share/vm/opto/callGenerator.cpp +++ b/src/share/vm/opto/callGenerator.cpp @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "ci/bcEscapeAnalyzer.hpp" #include "ci/ciCallSite.hpp" -#include "ci/ciCPCache.hpp" +#include "ci/ciObjArray.hpp" #include "ci/ciMemberName.hpp" #include "ci/ciMethodHandle.hpp" #include "classfile/javaClasses.hpp" @@ -167,7 +167,7 @@ public: VirtualCallGenerator(ciMethod* method, int vtable_index) : CallGenerator(method), _vtable_index(vtable_index) { - assert(vtable_index == methodOopDesc::invalid_vtable_index || + assert(vtable_index == Method::invalid_vtable_index || vtable_index >= 0, "either invalid or usable"); } virtual bool is_virtual() const { return true; } @@ -217,7 +217,7 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) { assert(!method()->is_static(), "virtual call must not be to static"); assert(!method()->is_final(), "virtual call should not be to final"); assert(!method()->is_private(), "virtual call should not be to private"); - assert(_vtable_index == methodOopDesc::invalid_vtable_index || !UseInlineCaches, + assert(_vtable_index == Method::invalid_vtable_index || !UseInlineCaches, "no vtable calls if +UseInlineCaches "); address target = SharedRuntime::get_resolve_virtual_call_stub(); // Normal inline cache used for call @@ -603,7 +603,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget(); guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove - const int vtable_index = methodOopDesc::invalid_vtable_index; + const int vtable_index = Method::invalid_vtable_index; CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS); if (cg != NULL && cg->is_inline()) return cg; @@ -653,7 +653,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* } } } - const int vtable_index = methodOopDesc::invalid_vtable_index; + const int vtable_index = Method::invalid_vtable_index; const bool call_is_virtual = target->is_abstract(); // FIXME workaround CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS); if (cg != NULL && cg->is_inline()) diff --git a/src/share/vm/opto/callnode.cpp b/src/share/vm/opto/callnode.cpp index 2fdacf9f5..398497f9b 100644 --- a/src/share/vm/opto/callnode.cpp +++ b/src/share/vm/opto/callnode.cpp @@ -83,7 +83,7 @@ Node *StartNode::match( const ProjNode *proj, const Matcher *match ) { const Type *t = _domain->field_at(proj->_con); if (t->base() == Type::Half) // 2nd half of Longs and Doubles return new (match->C, 1) ConNode(Type::TOP); - uint ideal_reg = Matcher::base2reg[t->base()]; + uint ideal_reg = t->ideal_reg(); RegMask &rm = match->_calling_convention_mask[parm_num]; return new (match->C, 1) MachProjNode(this,proj->_con,rm,ideal_reg); } @@ -131,7 +131,7 @@ uint ParmNode::ideal_reg() const { case TypeFunc::Parms : { // Type of argument being passed const Type *t = in(0)->as_Start()->_domain->field_at(_con); - return Matcher::base2reg[t->base()]; + return t->ideal_reg(); } } ShouldNotReachHere(); @@ -344,10 +344,15 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c st->print(" %s%d]=#NULL",msg,i); break; case Type::AryPtr: - case Type::KlassPtr: case Type::InstPtr: st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->isa_oopptr()->const_oop()); break; + case Type::KlassPtr: + st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_klassptr()->klass()); + break; + case Type::MetadataPtr: + st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_metadataptr()->metadata()); + break; case Type::NarrowOop: st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_oopptr()->const_oop()); break; @@ -628,7 +633,7 @@ Node *CallNode::match( const ProjNode *proj, const Matcher *match ) { return new (match->C, 1) MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); case TypeFunc::Parms: { // Normal returns - uint ideal_reg = Matcher::base2reg[tf()->range()->field_at(TypeFunc::Parms)->base()]; + uint ideal_reg = tf()->range()->field_at(TypeFunc::Parms)->ideal_reg(); OptoRegPair regs = is_CallRuntime() ? match->c_return_value(ideal_reg,true) // Calls into C runtime : match-> return_value(ideal_reg,true); // Calls into compiled Java code diff --git a/src/share/vm/opto/cfgnode.cpp b/src/share/vm/opto/cfgnode.cpp index 4f01e8548..795673da2 100644 --- a/src/share/vm/opto/cfgnode.cpp +++ b/src/share/vm/opto/cfgnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -1936,7 +1936,7 @@ const RegMask &PhiNode::in_RegMask(uint i) const { } const RegMask &PhiNode::out_RegMask() const { - uint ideal_reg = Matcher::base2reg[_type->base()]; + uint ideal_reg = _type->ideal_reg(); assert( ideal_reg != Node::NotAMachineReg, "invalid type at Phi" ); if( ideal_reg == 0 ) return RegMask::Empty; return *(Compile::current()->matcher()->idealreg2spillmask[ideal_reg]); diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp index 01e4b3462..292c52412 100644 --- a/src/share/vm/opto/compile.cpp +++ b/src/share/vm/opto/compile.cpp @@ -925,17 +925,6 @@ Compile::Compile( ciEnv* ci_env, } } -#ifndef PRODUCT -void print_opto_verbose_signature( const TypeFunc *j_sig, const char *stub_name ) { - if(PrintOpto && Verbose) { - tty->print("%s ", stub_name); j_sig->print_flattened(); tty->cr(); - } -} -#endif - -void Compile::print_codes() { -} - //------------------------------Init------------------------------------------- // Prepare for a single compilation void Compile::Init(int aliaslevel) { @@ -963,7 +952,7 @@ void Compile::Init(int aliaslevel) { set_recent_alloc(NULL, NULL); // Create Debug Information Recorder to record scopes, oopmaps, etc. - env()->set_oop_recorder(new OopRecorder(comp_arena())); + env()->set_oop_recorder(new OopRecorder(env()->arena())); env()->set_debug_info(new DebugInformationRecorder(env()->oop_recorder())); env()->set_dependencies(new Dependencies(env())); @@ -1182,7 +1171,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { // space to include all of the array body. Only the header, klass // and array length can be accessed un-aliased. if( offset != Type::OffsetBot ) { - if( ta->const_oop() ) { // methodDataOop or methodOop + if( ta->const_oop() ) { // MethodData* or Method* offset = Type::OffsetBot; // Flatten constant access into array body tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,offset); } else if( offset == arrayOopDesc::length_offset_in_bytes() ) { @@ -3026,12 +3015,13 @@ bool Compile::Constant::operator==(const Constant& other) { 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_FLOAT: return (_v._value.i == other._v._value.i); case T_LONG: - case T_DOUBLE: return (_value.j == other._value.j); + case T_DOUBLE: return (_v._value.j == other._v._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 + case T_METADATA: return (_v._metadata == other._v._metadata); + case T_ADDRESS: return (_v._value.l == other._v._value.l); + case T_VOID: return (_v._value.l == other._v._value.l); // jump-table entries default: ShouldNotReachHere(); } return false; @@ -3042,6 +3032,7 @@ static int type_to_size_in_bytes(BasicType t) { case T_LONG: return sizeof(jlong ); case T_FLOAT: return sizeof(jfloat ); case T_DOUBLE: return sizeof(jdouble); + case T_METADATA: return sizeof(Metadata*); // We use T_VOID as marker for jump-table entries (labels) which // need an internal word relocation. case T_VOID: @@ -3135,6 +3126,12 @@ void Compile::ConstantTable::emit(CodeBuffer& cb) { } break; } + case T_METADATA: { + Metadata* obj = con.get_metadata(); + int metadata_index = _masm.oop_recorder()->find_index(obj); + constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index)); + break; + } default: ShouldNotReachHere(); } assert(constant_addr, "consts section too small"); @@ -3168,6 +3165,12 @@ Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType typ return con; } +Compile::Constant Compile::ConstantTable::add(Metadata* metadata) { + Constant con(metadata); + add(con); + return con; +} + Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) { jvalue value; BasicType type = oper->type()->basic_type(); @@ -3177,7 +3180,8 @@ Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* ope case T_DOUBLE: value.d = oper->constantD(); break; case T_OBJECT: case T_ADDRESS: value.l = (jobject) oper->constant(); break; - default: ShouldNotReachHere(); + case T_METADATA: return add((Metadata*)oper->constant()); break; + default: guarantee(false, err_msg_res("unhandled type: %s", type2name(type))); } return add(n, type, value); } diff --git a/src/share/vm/opto/compile.hpp b/src/share/vm/opto/compile.hpp index 5e85802f9..a594b0913 100644 --- a/src/share/vm/opto/compile.hpp +++ b/src/share/vm/opto/compile.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -141,36 +141,51 @@ class Compile : public Phase { }; struct AliasCacheEntry { const TypePtr* _adr_type; int _index; }; // simple duple type enum { - trapHistLength = methodDataOopDesc::_trap_hist_limit + trapHistLength = MethodData::_trap_hist_limit }; // Constant entry of the constant table. class Constant { private: BasicType _type; + union { jvalue _value; + Metadata* _metadata; + } _v; int _offset; // offset of this constant (in bytes) relative to the constant table base. float _freq; bool _can_be_reused; // true (default) if the value can be shared with other users. public: - Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _value.l = 0; } + Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; } Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) : _type(type), - _value(value), _offset(-1), _freq(freq), _can_be_reused(can_be_reused) - {} + { + assert(type != T_METADATA, "wrong constructor"); + _v._value = value; + } + Constant(Metadata* metadata, bool can_be_reused = true) : + _type(T_METADATA), + _offset(-1), + _freq(0.0f), + _can_be_reused(can_be_reused) + { + _v._metadata = metadata; + } bool operator==(const Constant& other); BasicType type() const { return _type; } - jlong get_jlong() const { return _value.j; } - jfloat get_jfloat() const { return _value.f; } - jdouble get_jdouble() const { return _value.d; } - jobject get_jobject() const { return _value.l; } + jlong get_jlong() const { return _v._value.j; } + jfloat get_jfloat() const { return _v._value.f; } + jdouble get_jdouble() const { return _v._value.d; } + jobject get_jobject() const { return _v._value.l; } + + Metadata* get_metadata() const { return _v._metadata; } int offset() const { return _offset; } void set_offset(int offset) { _offset = offset; } @@ -219,6 +234,7 @@ class Compile : public Phase { void add(Constant& con); Constant add(MachConstantNode* n, BasicType type, jvalue value); + Constant add(Metadata* metadata); Constant add(MachConstantNode* n, MachOper* oper); Constant add(MachConstantNode* n, jfloat f) { jvalue value; value.f = f; @@ -270,7 +286,7 @@ class Compile : public Phase { bool _do_scheduling; // True if we intend to do scheduling bool _do_freq_based_layout; // True if we intend to do frequency based block layout bool _do_count_invocations; // True if we generate code to count invocations - bool _do_method_data_update; // True if we generate code to update methodDataOops + bool _do_method_data_update; // True if we generate code to update MethodData*s int _AliasLevel; // Locally-adjusted version of AliasLevel flag. bool _print_assembly; // True if we should dump assembly code for this compilation #ifndef PRODUCT @@ -896,9 +912,6 @@ class Compile : public Phase { // graph is strongly connected from root in both directions. void verify_graph_edges(bool no_dead_code = false) PRODUCT_RETURN; - // Print bytecodes, including the scope inlining tree - void print_codes(); - // End-of-run dumps. static void print_statistics() PRODUCT_RETURN; diff --git a/src/share/vm/opto/connode.cpp b/src/share/vm/opto/connode.cpp index 7e072ff44..e038ccbc2 100644 --- a/src/share/vm/opto/connode.cpp +++ b/src/share/vm/opto/connode.cpp @@ -50,10 +50,11 @@ ConNode *ConNode::make( Compile* C, const Type *t ) { case T_FLOAT: return new (C, 1) ConFNode( t->is_float_constant() ); case T_DOUBLE: return new (C, 1) ConDNode( t->is_double_constant() ); case T_VOID: return new (C, 1) ConNode ( Type::TOP ); - case T_OBJECT: return new (C, 1) ConPNode( t->is_oopptr() ); + case T_OBJECT: return new (C, 1) ConPNode( t->is_ptr() ); case T_ARRAY: return new (C, 1) ConPNode( t->is_aryptr() ); case T_ADDRESS: return new (C, 1) ConPNode( t->is_ptr() ); case T_NARROWOOP: return new (C, 1) ConNNode( t->is_narrowoop() ); + case T_METADATA: return new (C, 1) ConPNode( t->is_ptr() ); // Expected cases: TypePtr::NULL_PTR, any is_rawptr() // Also seen: AnyPtr(TopPTR *+top); from command line: // r -XX:+PrintOpto -XX:CIStart=285 -XX:+CompileTheWorld -XX:CompileTheWorldStartAt=660 @@ -526,8 +527,8 @@ const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const { // // If either input is an 'interface', return destination type // assert (in_oop == NULL || in_oop->klass() != NULL, ""); // assert (my_oop == NULL || my_oop->klass() != NULL, ""); - // if( (in_oop && in_oop->klass()->klass_part()->is_interface()) - // ||(my_oop && my_oop->klass()->klass_part()->is_interface()) ) { + // if( (in_oop && in_oop->klass()->is_interface()) + // ||(my_oop && my_oop->klass()->is_interface()) ) { // TypePtr::PTR in_ptr = in->isa_ptr() ? in->is_ptr()->_ptr : TypePtr::BotPTR; // // Preserve cast away nullness for interfaces // if( in_ptr == TypePtr::NotNull && my_oop && my_oop->_ptr == TypePtr::BotPTR ) { @@ -604,7 +605,7 @@ const Type *EncodePNode::Value( PhaseTransform *phase ) const { if (t == Type::TOP) return Type::TOP; if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR; - assert(t->isa_oopptr(), "only oopptr here"); + assert(t->isa_oop_ptr() || UseCompressedKlassPointers && t->isa_klassptr(), "only oopptr here"); return t->make_narrowoop(); } diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp index a34870509..c8576dc50 100644 --- a/src/share/vm/opto/doCall.cpp +++ b/src/share/vm/opto/doCall.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" -#include "ci/ciCPCache.hpp" #include "ci/ciCallSite.hpp" #include "ci/ciMethodHandle.hpp" #include "classfile/vmSymbols.hpp" @@ -392,7 +391,7 @@ void Parse::do_call() { // Choose call strategy. bool call_is_virtual = is_virtual_or_interface; - int vtable_index = methodOopDesc::invalid_vtable_index; + int vtable_index = Method::invalid_vtable_index; ciMethod* callee = orig_callee; // Try to get the most accurate receiver type @@ -539,7 +538,7 @@ void Parse::do_call() { } } } else { - assert(ct == rt, err_msg_res("unexpected mismatch rt=%d, ct=%d", rt, ct)); + assert(ct == rt, err_msg("unexpected mismatch rt=%d, ct=%d", rt, ct)); // push a zero; it's better than getting an oop/int mismatch retnode = pop_node(rt); retnode = zerocon(ct); @@ -836,9 +835,9 @@ void Parse::count_compiled_calls(bool at_method_entry, bool is_inline) { if( at_method_entry ) { // bump invocation counter if top method (for statistics) if (CountCompiledCalls && depth() == 1) { - const TypeOopPtr* addr_type = TypeOopPtr::make_from_constant(method()); + const TypePtr* addr_type = TypeMetadataPtr::make(method()); Node* adr1 = makecon(addr_type); - Node* adr2 = basic_plus_adr(adr1, adr1, in_bytes(methodOopDesc::compiled_invocation_counter_offset())); + Node* adr2 = basic_plus_adr(adr1, adr1, in_bytes(Method::compiled_invocation_counter_offset())); increment_counter(adr2); } } else if (is_inline) { diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp index f844eaaa4..200122620 100644 --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -3446,12 +3446,6 @@ void GraphKit::write_barrier_post(Node* oop_store, if (t == TypePtr::NULL_PTR || t == Type::TOP) // stores of null never (?) need barriers return; - ciObject* con = t->is_oopptr()->const_oop(); - if (con != NULL - && con->is_perm() - && Universe::heap()->can_elide_permanent_oop_store_barriers()) - // no store barrier needed, because no old-to-new ref created - return; } if (use_ReduceInitialCardMarks() diff --git a/src/share/vm/opto/graphKit.hpp b/src/share/vm/opto/graphKit.hpp index c32575d07..2c09486c3 100644 --- a/src/share/vm/opto/graphKit.hpp +++ b/src/share/vm/opto/graphKit.hpp @@ -743,7 +743,7 @@ class GraphKit : public Phase { void shared_unlock(Node* box, Node* obj); // helper functions for the fast path/slow path idioms - Node* fast_and_slow(Node* in, const Type *result_type, Node* null_result, IfNode* fast_test, Node* fast_result, address slow_call, const TypeFunc *slow_call_type, Node* slow_arg, klassOop ex_klass, Node* slow_result); + Node* fast_and_slow(Node* in, const Type *result_type, Node* null_result, IfNode* fast_test, Node* fast_result, address slow_call, const TypeFunc *slow_call_type, Node* slow_arg, Klass* ex_klass, Node* slow_result); // Generate an instance-of idiom. Used by both the instance-of bytecode // and the reflective instance-of call. diff --git a/src/share/vm/opto/idealGraphPrinter.cpp b/src/share/vm/opto/idealGraphPrinter.cpp index b3919a654..0928704d9 100644 --- a/src/share/vm/opto/idealGraphPrinter.cpp +++ b/src/share/vm/opto/idealGraphPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2012, 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 @@ -407,7 +407,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { node->_in_dump_cnt++; print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); const Type *t = node->bottom_type(); - print_prop("type", (const char *)Type::msg[t->base()]); + print_prop("type", t->msg()); print_prop("idx", node->_idx); #ifdef ASSERT print_prop("debug_idx", node->_debug_idx); diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp index 3ae12baa7..832799a58 100644 --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -2904,11 +2904,11 @@ bool LibraryCallKit::inline_unsafe_allocate() { // Note: The argument might still be an illegal value like // Serializable.class or Object[].class. The runtime will handle it. // But we must make an explicit check for initialization. - Node* insp = basic_plus_adr(kls, in_bytes(instanceKlass::init_state_offset())); - // Use T_BOOLEAN for instanceKlass::_init_state so the compiler + Node* insp = basic_plus_adr(kls, in_bytes(InstanceKlass::init_state_offset())); + // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler // can generate code to load it as unsigned byte. Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN); - Node* bits = intcon(instanceKlass::fully_initialized); + Node* bits = intcon(InstanceKlass::fully_initialized); Node* test = _gvn.transform( new (C, 3) SubINode(inst, bits) ); // The 'test' is non-zero if we need to take a slow path. @@ -3475,7 +3475,7 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, if (layout_val == NULL) { bool query = (obj_array ? Klass::layout_helper_is_objArray(layout_con) - : Klass::layout_helper_is_javaArray(layout_con)); + : Klass::layout_helper_is_array(layout_con)); if (query == not_array) { return NULL; // never a branch } else { // always a branch @@ -3710,15 +3710,15 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, RegionNode* slow_region) { ciMethod* method = callee(); int vtable_index = method->vtable_index(); - // Get the methodOop out of the appropriate vtable entry. - int entry_offset = (instanceKlass::vtable_start_offset() + + // Get the Method* out of the appropriate vtable entry. + int entry_offset = (InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size()) * wordSize + vtableEntry::method_offset_in_bytes(); Node* entry_addr = basic_plus_adr(obj_klass, entry_offset); Node* target_call = make_load(NULL, entry_addr, TypeInstPtr::NOTNULL, T_OBJECT); // Compare the target method with the expected method (e.g., Object.hashCode). - const TypeInstPtr* native_call_addr = TypeInstPtr::make(method); + const TypePtr* native_call_addr = TypeMetadataPtr::make(method); Node* native_call = makecon(native_call_addr); Node* chk_native = _gvn.transform( new(C, 3) CmpPNode(target_call, native_call) ); @@ -3753,7 +3753,7 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual method, bci()); } else if (is_virtual) { null_check_receiver(method); - int vtable_index = methodOopDesc::invalid_vtable_index; + int vtable_index = Method::invalid_vtable_index; if (UseInlineCaches) { // Suppress the vtable call } else { @@ -4266,8 +4266,8 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b instanceOopDesc::base_offset_in_bytes(); // base_off: // 8 - 32-bit VM - // 12 - 64-bit VM, compressed oops - // 16 - 64-bit VM, normal oops + // 12 - 64-bit VM, compressed klass + // 16 - 64-bit VM, normal klass if (base_off % BytesPerLong != 0) { assert(UseCompressedOops, ""); if (is_array) { @@ -4899,7 +4899,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, // further to JVM_ArrayCopy on the first per-oop check that fails. // (Actually, we don't move raw bits only; the GC requires card marks.) - // Get the klassOop for both src and dest + // Get the Klass* for both src and dest Node* src_klass = load_object_klass(src); Node* dest_klass = load_object_klass(dest); diff --git a/src/share/vm/opto/machnode.cpp b/src/share/vm/opto/machnode.cpp index 88bb23b37..2a5d96369 100644 --- a/src/share/vm/opto/machnode.cpp +++ b/src/share/vm/opto/machnode.cpp @@ -38,7 +38,7 @@ int MachOper::reg(PhaseRegAlloc *ra_, const Node *node, int idx) const { return (int)(ra_->get_encode(node->in(idx))); } intptr_t MachOper::constant() const { return 0x00; } -bool MachOper::constant_is_oop() const { return false; } +relocInfo::relocType MachOper::constant_reloc() const { return relocInfo::none; } jdouble MachOper::constantD() const { ShouldNotReachHere(); return 0.0; } jfloat MachOper::constantF() const { ShouldNotReachHere(); return 0.0; } jlong MachOper::constantL() const { ShouldNotReachHere(); return CONST64(0) ; } @@ -54,7 +54,7 @@ int MachOper::constant_disp() const { return 0; } int MachOper::base_position() const { return -1; } // no base input int MachOper::index_position() const { return -1; } // no index input // Check for PC-Relative displacement -bool MachOper::disp_is_oop() const { return false; } +relocInfo::relocType MachOper::disp_reloc() const { return relocInfo::none; } // Return the label Label* MachOper::label() const { ShouldNotReachHere(); return 0; } intptr_t MachOper::method() const { ShouldNotReachHere(); return 0; } diff --git a/src/share/vm/opto/machnode.hpp b/src/share/vm/opto/machnode.hpp index 4db1154e8..5b630e45c 100644 --- a/src/share/vm/opto/machnode.hpp +++ b/src/share/vm/opto/machnode.hpp @@ -104,7 +104,7 @@ public: #endif virtual intptr_t constant() const; - virtual bool constant_is_oop() const; + virtual relocInfo::relocType constant_reloc() const; virtual jdouble constantD() const; virtual jfloat constantF() const; virtual jlong constantL() const; @@ -118,7 +118,7 @@ public: // Parameters needed to support MEMORY_INTERFACE access to stackSlot virtual int disp (PhaseRegAlloc *ra_, const Node *node, int idx) const; // Check for PC-Relative displacement - virtual bool disp_is_oop() const; + virtual relocInfo::relocType disp_reloc() const; virtual int constant_disp() const; // usu. 0, may return Type::OffsetBot virtual int base_position() const; // base edge position, or -1 virtual int index_position() const; // index edge position, or -1 @@ -247,7 +247,7 @@ public: // Bottom_type call; value comes from operand0 virtual const class Type *bottom_type() const { return _opnds[0]->type(); } - virtual uint ideal_reg() const { const Type *t = _opnds[0]->type(); return t == TypeInt::CC ? Op_RegFlags : Matcher::base2reg[t->base()]; } + virtual uint ideal_reg() const { const Type *t = _opnds[0]->type(); return t == TypeInt::CC ? Op_RegFlags : t->ideal_reg(); } // If this is a memory op, return the base pointer and fixed offset. // If there are no such, return NULL. If there are multiple addresses @@ -498,7 +498,7 @@ public: virtual const RegMask &out_RegMask() const { return *_out; } virtual const RegMask &in_RegMask(uint) const { return *_in; } virtual const class Type *bottom_type() const { return _type; } - virtual uint ideal_reg() const { return Matcher::base2reg[_type->base()]; } + virtual uint ideal_reg() const { return _type->ideal_reg(); } virtual uint oper_input_base() const { return 1; } uint implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const; diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp index fee17c48a..a5250292b 100644 --- a/src/share/vm/opto/macro.cpp +++ b/src/share/vm/opto/macro.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -1567,7 +1567,7 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc, } rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS); - rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_OBJECT); + rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_METADATA); int header_size = alloc->minimum_header_size(); // conservatively small // Array length diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp index d5f14f4f6..bf4a345ce 100644 --- a/src/share/vm/opto/matcher.cpp +++ b/src/share/vm/opto/matcher.cpp @@ -198,7 +198,7 @@ void Matcher::match( ) { const TypeTuple *range = C->tf()->range(); if( range->cnt() > TypeFunc::Parms ) { // If not a void function // Get ideal-register return type - int ireg = base2reg[range->field_at(TypeFunc::Parms)->base()]; + int ireg = range->field_at(TypeFunc::Parms)->ideal_reg(); // Get machine return register uint sop = C->start()->Opcode(); OptoRegPair regs = return_value(ireg, false); @@ -1285,7 +1285,7 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { // a little in-place argument insertion. // FIXME: Is this still necessary? int regs_per_word = NOT_LP64(1) LP64_ONLY(2); // %%% make a global const! - out_arg_limit_per_call += methodOopDesc::extra_stack_entries() * regs_per_word; + out_arg_limit_per_call += Method::extra_stack_entries() * regs_per_word; // Do not update mcall->_argsize because (a) the extra space is not // pushed as arguments and (b) _argsize is dead (not used anywhere). } diff --git a/src/share/vm/opto/matcher.hpp b/src/share/vm/opto/matcher.hpp index 0597cb543..51282db37 100644 --- a/src/share/vm/opto/matcher.hpp +++ b/src/share/vm/opto/matcher.hpp @@ -123,7 +123,6 @@ class Matcher : public PhaseTransform { public: int LabelRootDepth; - static const int base2reg[]; // Map Types to machine register types // Convert ideal machine register to a register mask for spill-loads static const RegMask *idealreg2regmask[]; RegMask *idealreg2spillmask [_last_machine_leaf]; diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp index 799c2ba14..1cbe31756 100644 --- a/src/share/vm/opto/memnode.cpp +++ b/src/share/vm/opto/memnode.cpp @@ -841,7 +841,7 @@ uint LoadNode::cmp( const Node &n ) const { return !Type::cmp( _type, ((LoadNode&)n)._type ); } const Type *LoadNode::bottom_type() const { return _type; } uint LoadNode::ideal_reg() const { - return Matcher::base2reg[_type->base()]; + return _type->ideal_reg(); } #ifndef PRODUCT @@ -1660,7 +1660,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { return TypeInt::make(klass->super_check_offset()); } // Compute index into primary_supers array - juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(klassOop); + juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*); // Check for overflowing; use unsigned compare to handle the negative case. if( depth < ciKlass::primary_super_limit() ) { // The field is an element of Klass::_primary_supers. Return its (constant) value. @@ -1690,13 +1690,13 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { // shallow enough depth. Even though the klass is not exact, entries less // than or equal to its super depth are correct. if (klass->is_loaded() ) { - ciType *inner = klass->klass(); + ciType *inner = klass; while( inner->is_obj_array_klass() ) inner = inner->as_obj_array_klass()->base_element_type(); if( inner->is_instance_klass() && !inner->as_instance_klass()->flags().is_interface() ) { // Compute index into primary_supers array - juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(klassOop); + juint depth = (tkls->offset() - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*); // Check for overflowing; use unsigned compare to handle the negative case. if( depth < ciKlass::primary_super_limit() && depth <= klass->super_depth() ) { // allow self-depth checks to handle self-check case @@ -1891,10 +1891,11 @@ Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* a Compile* C = gvn.C; Node *ctl = NULL; // sanity check the alias category against the created node type - const TypeOopPtr *adr_type = adr->bottom_type()->isa_oopptr(); - assert(adr_type != NULL, "expecting TypeOopPtr"); + const TypePtr *adr_type = adr->bottom_type()->isa_ptr(); + assert(adr_type != NULL, "expecting TypeKlassPtr"); #ifdef _LP64 if (adr_type->is_ptr_to_narrowoop()) { + assert(UseCompressedKlassPointers, "no compressed klasses"); Node* load_klass = gvn.transform(new (C, 3) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowoop())); return new (C, 2) DecodeNNode(load_klass, load_klass->bottom_type()->make_ptr()); } @@ -2065,7 +2066,7 @@ Node* LoadNode::klass_identity_common(PhaseTransform *phase ) { } } - // Simplify k.java_mirror.as_klass to plain k, where k is a klassOop. + // Simplify k.java_mirror.as_klass to plain k, where k is a Klass*. // Simplify ak.component_mirror.array_klass to plain ak, ak an arrayKlass. // See inline_native_Class_query for occurrences of these patterns. // Java Example: x.getClass().isAssignableFrom(y) @@ -2074,7 +2075,7 @@ Node* LoadNode::klass_identity_common(PhaseTransform *phase ) { // This improves reflective code, often making the Class // mirror go completely dead. (Current exception: Class // mirrors may appear in debug info, but we could clean them out by - // introducing a new debug info operator for klassOop.java_mirror). + // introducing a new debug info operator for Klass*.java_mirror). if (toop->isa_instptr() && toop->klass() == phase->C->env()->Class_klass() && (offset == java_lang_Class::klass_offset_in_bytes() || offset == java_lang_Class::array_klass_offset_in_bytes())) { @@ -2223,11 +2224,12 @@ StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, cons case T_LONG: return new (C, 4) StoreLNode(ctl, mem, adr, adr_type, val); case T_FLOAT: return new (C, 4) StoreFNode(ctl, mem, adr, adr_type, val); case T_DOUBLE: return new (C, 4) StoreDNode(ctl, mem, adr, adr_type, val); + case T_METADATA: case T_ADDRESS: case T_OBJECT: #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop() || - (UseCompressedOops && val->bottom_type()->isa_klassptr() && + (UseCompressedKlassPointers && val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { val = gvn.transform(new (C, 2) EncodePNode(val, val->bottom_type()->make_narrowoop())); return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, val); diff --git a/src/share/vm/opto/multnode.cpp b/src/share/vm/opto/multnode.cpp index fb29e1ea4..280414106 100644 --- a/src/share/vm/opto/multnode.cpp +++ b/src/share/vm/opto/multnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -130,5 +130,5 @@ const RegMask &ProjNode::out_RegMask() const { //------------------------------ideal_reg-------------------------------------- uint ProjNode::ideal_reg() const { - return Matcher::base2reg[bottom_type()->base()]; + return bottom_type()->ideal_reg(); } diff --git a/src/share/vm/opto/node.cpp b/src/share/vm/opto/node.cpp index 2cb44ad0e..880576016 100644 --- a/src/share/vm/opto/node.cpp +++ b/src/share/vm/opto/node.cpp @@ -2057,5 +2057,5 @@ const Type *TypeNode::Value( PhaseTransform * ) const { return _type; } //------------------------------ideal_reg-------------------------------------- uint TypeNode::ideal_reg() const { - return Matcher::base2reg[_type->base()]; + return _type->ideal_reg(); } diff --git a/src/share/vm/opto/output.cpp b/src/share/vm/opto/output.cpp index 261792e49..89b62127e 100644 --- a/src/share/vm/opto/output.cpp +++ b/src/share/vm/opto/output.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -626,7 +626,7 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, assert(cik->is_instance_klass() || cik->is_array_klass(), "Not supported allocation."); sv = new ObjectValue(spobj->_idx, - new ConstantOopWriteValue(cik->constant_encoding())); + new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); Compile::set_sv_for_object_node(objs, sv); uint first_ind = spobj->first_index(); @@ -715,8 +715,7 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, array->append(new ConstantOopWriteValue(NULL)); break; case Type::AryPtr: - case Type::InstPtr: - case Type::KlassPtr: // fall through + case Type::InstPtr: // fall through array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->constant_encoding())); break; case Type::NarrowOop: @@ -902,7 +901,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { assert(cik->is_instance_klass() || cik->is_array_klass(), "Not supported allocation."); ObjectValue* sv = new ObjectValue(spobj->_idx, - new ConstantOopWriteValue(cik->constant_encoding())); + new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); Compile::set_sv_for_object_node(objs, sv); uint first_ind = spobj->first_index(); @@ -1658,8 +1657,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { ""); } if (method() != NULL) { - method()->print_oop(); - print_codes(); + method()->print_metadata(); } dump_asm(node_offsets, node_offset_limit); if (xtty != NULL) { diff --git a/src/share/vm/opto/parse1.cpp b/src/share/vm/opto/parse1.cpp index 79fab69c1..8eb86d7bf 100644 --- a/src/share/vm/opto/parse1.cpp +++ b/src/share/vm/opto/parse1.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "compiler/compileLog.hpp" #include "interpreter/linkResolver.hpp" -#include "oops/methodOop.hpp" +#include "oops/method.hpp" #include "opto/addnode.hpp" #include "opto/idealGraphPrinter.hpp" #include "opto/locknode.hpp" @@ -492,7 +492,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) if (PrintOpto && (Verbose || WizardMode)) { tty->print_cr("OSR @%d type flow bailout: %s", _entry_bci, _flow->failure_reason()); if (Verbose) { - method()->print_oop(); + method()->print(); method()->print_codes(); _flow->print(); } diff --git a/src/share/vm/opto/parse2.cpp b/src/share/vm/opto/parse2.cpp index 4982a1d76..af514850b 100644 --- a/src/share/vm/opto/parse2.cpp +++ b/src/share/vm/opto/parse2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -1447,7 +1447,7 @@ void Parse::do_one_bytecode() { NULL, tag.internal_name()); break; } - assert(constant.basic_type() != T_OBJECT || !constant.as_object()->is_klass(), + assert(constant.basic_type() != T_OBJECT || constant.as_object()->is_instance(), "must be java_mirror of klass"); bool pushed = push_constant(constant, true); guarantee(pushed, "must be possible to push this constant"); diff --git a/src/share/vm/opto/parseHelper.cpp b/src/share/vm/opto/parseHelper.cpp index 26a146f5e..e562d2772 100644 --- a/src/share/vm/opto/parseHelper.cpp +++ b/src/share/vm/opto/parseHelper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -46,7 +46,7 @@ void GraphKit::make_dtrace_method_entry_exit(ciMethod* method, bool is_entry) { Node* thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); // Get method - const TypeInstPtr* method_type = TypeInstPtr::make(TypePtr::Constant, method->klass(), true, method, 0); + const TypePtr* method_type = TypeMetadataPtr::make(method); Node *method_node = _gvn.transform( ConNode::make(C, method_type) ); kill_dead_locals(); @@ -220,7 +220,7 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) { _gvn.set_type(merge, Type::CONTROL); Node* kls = makecon(TypeKlassPtr::make(klass)); - Node* init_thread_offset = _gvn.MakeConX(in_bytes(instanceKlass::init_thread_offset())); + Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset())); Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); @@ -228,12 +228,12 @@ void Parse::emit_guard_for_new(ciInstanceKlass* klass) { set_control(IfTrue(iff)); merge->set_req(1, IfFalse(iff)); - Node* init_state_offset = _gvn.MakeConX(in_bytes(instanceKlass::init_state_offset())); + Node* init_state_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_state_offset())); adr_node = basic_plus_adr(kls, kls, init_state_offset); - // Use T_BOOLEAN for instanceKlass::_init_state so the compiler + // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler // can generate code to load it as unsigned byte. Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN); - Node* being_init = _gvn.intcon(instanceKlass::being_initialized); + Node* being_init = _gvn.intcon(InstanceKlass::being_initialized); tst = Bool( CmpI( init_state, being_init), BoolTest::eq); iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); @@ -336,13 +336,13 @@ void Parse::test_counter_against_threshold(Node* cnt, int limit) { void Parse::increment_and_test_invocation_counter(int limit) { if (!count_invocations()) return; - // Get the methodOop node. - const TypePtr* adr_type = TypeOopPtr::make_from_constant(method()); - Node *methodOop_node = makecon(adr_type); + // Get the Method* node. + const TypePtr* adr_type = TypeMetadataPtr::make(method()); + Node *method_node = makecon(adr_type); - // Load the interpreter_invocation_counter from the methodOop. - int offset = methodOopDesc::interpreter_invocation_counter_offset_in_bytes(); - Node* adr_node = basic_plus_adr(methodOop_node, methodOop_node, offset); + // Load the interpreter_invocation_counter from the Method*. + int offset = Method::interpreter_invocation_counter_offset_in_bytes(); + Node* adr_node = basic_plus_adr(method_node, method_node, offset); Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); test_counter_against_threshold(cnt, limit); @@ -354,8 +354,8 @@ void Parse::increment_and_test_invocation_counter(int limit) { //----------------------------method_data_addressing--------------------------- Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { - // Get offset within methodDataOop of the data array - ByteSize data_offset = methodDataOopDesc::data_offset(); + // Get offset within MethodData* of the data array + ByteSize data_offset = MethodData::data_offset(); // Get cell offset of the ProfileData within data array int cell_offset = md->dp_to_di(data->dp()); @@ -363,7 +363,7 @@ Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteS // Add in counter_offset, the # of bytes into the ProfileData of counter or flag int offset = in_bytes(data_offset) + cell_offset + in_bytes(counter_offset); - const TypePtr* adr_type = TypeOopPtr::make_from_constant(md); + const TypePtr* adr_type = TypeMetadataPtr::make(md); Node* mdo = makecon(adr_type); Node* ptr = basic_plus_adr(mdo, mdo, offset); diff --git a/src/share/vm/opto/reg_split.cpp b/src/share/vm/opto/reg_split.cpp index 2c488894a..5e0dad80d 100644 --- a/src/share/vm/opto/reg_split.cpp +++ b/src/share/vm/opto/reg_split.cpp @@ -1196,7 +1196,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if( OptoReg::is_stack(uselrg.reg()) && uselrg.reg() < LRG::SPILL_REG && // USE is from stack deflrg.reg() != uselrg.reg() ) { // Not trivially removed - uint def_ideal_reg = Matcher::base2reg[n->bottom_type()->base()]; + uint def_ideal_reg = n->bottom_type()->ideal_reg(); const RegMask &def_rm = *Matcher::idealreg2regmask[def_ideal_reg]; const RegMask &use_rm = n->in_RegMask(copyidx); if( def_rm.overlap(use_rm) && n->is_SpillCopy() ) { // Bug 4707800, 'n' may be a storeSSL diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp index 75e6d7515..f6364a7b7 100644 --- a/src/share/vm/opto/runtime.cpp +++ b/src/share/vm/opto/runtime.cpp @@ -228,7 +228,7 @@ void OptoRuntime::new_store_pre_barrier(JavaThread* thread) { } // object allocation -JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(klassOopDesc* klass, JavaThread* thread)) +JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thread)) JRT_BLOCK; #ifndef PRODUCT SharedRuntime::_new_instance_ctr++; // new instance requires GC @@ -238,11 +238,11 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(klassOopDesc* klass, JavaThrea // These checks are cheap to make and support reflective allocation. int lh = Klass::cast(klass)->layout_helper(); if (Klass::layout_helper_needs_slow_path(lh) - || !instanceKlass::cast(klass)->is_initialized()) { + || !InstanceKlass::cast(klass)->is_initialized()) { KlassHandle kh(THREAD, klass); kh->check_valid_for_instantiation(false, THREAD); if (!HAS_PENDING_EXCEPTION) { - instanceKlass::cast(kh())->initialize(THREAD); + InstanceKlass::cast(kh())->initialize(THREAD); } if (!HAS_PENDING_EXCEPTION) { klass = kh(); @@ -253,7 +253,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(klassOopDesc* klass, JavaThrea if (klass != NULL) { // Scavenge and allocate an instance. - oop result = instanceKlass::cast(klass)->allocate_instance(THREAD); + oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); thread->set_vm_result(result); // Pass oops back through thread local storage. Our apparent type to Java @@ -273,7 +273,7 @@ JRT_END // array allocation -JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len, JavaThread *thread)) +JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaThread *thread)) JRT_BLOCK; #ifndef PRODUCT SharedRuntime::_new_array_ctr++; // new array requires GC @@ -292,7 +292,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len // Although the oopFactory likes to work with the elem_type, // the compiler prefers the array_type, since it must already have // that latter value in hand for the fast path. - klassOopDesc* elem_type = objArrayKlass::cast(array_type)->element_klass(); + Klass* elem_type = objArrayKlass::cast(array_type)->element_klass(); result = oopFactory::new_objArray(elem_type, len, THREAD); } @@ -311,7 +311,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len JRT_END // array allocation without zeroing -JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(klassOopDesc* array_type, int len, JavaThread *thread)) +JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread *thread)) JRT_BLOCK; #ifndef PRODUCT SharedRuntime::_new_array_ctr++; // new array requires GC @@ -361,12 +361,12 @@ JRT_END // Note: multianewarray for one dimension is handled inline by GraphKit::new_array. // multianewarray for 2 dimensions -JRT_ENTRY(void, OptoRuntime::multianewarray2_C(klassOopDesc* elem_type, int len1, int len2, JavaThread *thread)) +JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int len2, JavaThread *thread)) #ifndef PRODUCT SharedRuntime::_multi2_ctr++; // multianewarray for 1 dimension #endif assert(check_compiled_frame(thread), "incorrect caller"); - assert(oop(elem_type)->is_klass(), "not a class"); + assert(elem_type->is_klass(), "not a class"); jint dims[2]; dims[0] = len1; dims[1] = len2; @@ -376,12 +376,12 @@ JRT_ENTRY(void, OptoRuntime::multianewarray2_C(klassOopDesc* elem_type, int len1 JRT_END // multianewarray for 3 dimensions -JRT_ENTRY(void, OptoRuntime::multianewarray3_C(klassOopDesc* elem_type, int len1, int len2, int len3, JavaThread *thread)) +JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int len2, int len3, JavaThread *thread)) #ifndef PRODUCT SharedRuntime::_multi3_ctr++; // multianewarray for 1 dimension #endif assert(check_compiled_frame(thread), "incorrect caller"); - assert(oop(elem_type)->is_klass(), "not a class"); + assert(elem_type->is_klass(), "not a class"); jint dims[3]; dims[0] = len1; dims[1] = len2; @@ -392,12 +392,12 @@ JRT_ENTRY(void, OptoRuntime::multianewarray3_C(klassOopDesc* elem_type, int len1 JRT_END // multianewarray for 4 dimensions -JRT_ENTRY(void, OptoRuntime::multianewarray4_C(klassOopDesc* elem_type, int len1, int len2, int len3, int len4, JavaThread *thread)) +JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int len2, int len3, int len4, JavaThread *thread)) #ifndef PRODUCT SharedRuntime::_multi4_ctr++; // multianewarray for 1 dimension #endif assert(check_compiled_frame(thread), "incorrect caller"); - assert(oop(elem_type)->is_klass(), "not a class"); + assert(elem_type->is_klass(), "not a class"); jint dims[4]; dims[0] = len1; dims[1] = len2; @@ -409,12 +409,12 @@ JRT_ENTRY(void, OptoRuntime::multianewarray4_C(klassOopDesc* elem_type, int len1 JRT_END // multianewarray for 5 dimensions -JRT_ENTRY(void, OptoRuntime::multianewarray5_C(klassOopDesc* elem_type, int len1, int len2, int len3, int len4, int len5, JavaThread *thread)) +JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int len2, int len3, int len4, int len5, JavaThread *thread)) #ifndef PRODUCT SharedRuntime::_multi5_ctr++; // multianewarray for 1 dimension #endif assert(check_compiled_frame(thread), "incorrect caller"); - assert(oop(elem_type)->is_klass(), "not a class"); + assert(elem_type->is_klass(), "not a class"); jint dims[5]; dims[0] = len1; dims[1] = len2; @@ -426,9 +426,9 @@ JRT_ENTRY(void, OptoRuntime::multianewarray5_C(klassOopDesc* elem_type, int len1 thread->set_vm_result(obj); JRT_END -JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(klassOopDesc* elem_type, arrayOopDesc* dims, JavaThread *thread)) +JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* dims, JavaThread *thread)) assert(check_compiled_frame(thread), "incorrect caller"); - assert(oop(elem_type)->is_klass(), "not a class"); + assert(elem_type->is_klass(), "not a class"); assert(oop(dims)->is_typeArray(), "not an array"); ResourceMark rm; @@ -844,7 +844,7 @@ const TypeFunc* OptoRuntime::profile_receiver_type_Type() { JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* receiver)) if (receiver == NULL) return; - klassOop receiver_klass = receiver->klass(); + Klass* receiver_klass = receiver->klass(); intptr_t* mdp = ((intptr_t*)(data)) + DataLayout::header_size_in_cells(); int empty_row = -1; // free row, if any is encountered @@ -1148,7 +1148,7 @@ const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() { // create input type (domain) const Type **fields = TypeTuple::fields(2); fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage - fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // methodOop; Method we are entering + fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // Method*; Method we are entering const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); // create result type (range) @@ -1178,8 +1178,8 @@ const TypeFunc *OptoRuntime::dtrace_object_alloc_Type() { JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer(oopDesc* obj, JavaThread* thread)) assert(obj->is_oop(), "must be a valid oop"); - assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise"); - instanceKlass::register_finalizer(instanceOop(obj), CHECK); + assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise"); + InstanceKlass::register_finalizer(instanceOop(obj), CHECK); JRT_END //----------------------------------------------------------------------------- diff --git a/src/share/vm/opto/runtime.hpp b/src/share/vm/opto/runtime.hpp index 6037d19f2..c70777267 100644 --- a/src/share/vm/opto/runtime.hpp +++ b/src/share/vm/opto/runtime.hpp @@ -140,11 +140,11 @@ class OptoRuntime : public AllStatic { // ================================= // Allocate storage for a Java instance. - static void new_instance_C(klassOopDesc* instance_klass, JavaThread *thread); + static void new_instance_C(Klass* instance_klass, JavaThread *thread); // Allocate storage for a objArray or typeArray - static void new_array_C(klassOopDesc* array_klass, int len, JavaThread *thread); - static void new_array_nozero_C(klassOopDesc* array_klass, int len, JavaThread *thread); + static void new_array_C(Klass* array_klass, int len, JavaThread *thread); + static void new_array_nozero_C(Klass* array_klass, int len, JavaThread *thread); // Post-slow-path-allocation, pre-initializing-stores step for // implementing ReduceInitialCardMarks @@ -152,11 +152,11 @@ class OptoRuntime : public AllStatic { // Allocate storage for a multi-dimensional arrays // Note: needs to be fixed for arbitrary number of dimensions - static void multianewarray2_C(klassOopDesc* klass, int len1, int len2, JavaThread *thread); - static void multianewarray3_C(klassOopDesc* klass, int len1, int len2, int len3, JavaThread *thread); - static void multianewarray4_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, JavaThread *thread); - static void multianewarray5_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread); - static void multianewarrayN_C(klassOopDesc* klass, arrayOopDesc* dims, JavaThread *thread); + static void multianewarray2_C(Klass* klass, int len1, int len2, JavaThread *thread); + static void multianewarray3_C(Klass* klass, int len1, int len2, int len3, JavaThread *thread); + static void multianewarray4_C(Klass* klass, int len1, int len2, int len3, int len4, JavaThread *thread); + static void multianewarray5_C(Klass* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread); + static void multianewarrayN_C(Klass* klass, arrayOopDesc* dims, JavaThread *thread); static void g1_wb_pre_C(oopDesc* orig, JavaThread* thread); static void g1_wb_post_C(void* card_addr, JavaThread* thread); diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp index 02a6a6495..9ecd2db7d 100644 --- a/src/share/vm/opto/subnode.cpp +++ b/src/share/vm/opto/subnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -664,9 +664,7 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const { // See if neither subclasses the other, or if the class on top // is precise. In either of these cases, the compare is known // to fail if at least one of the pointers is provably not null. - if (klass0->equals(klass1) || // if types are unequal but klasses are - !klass0->is_java_klass() || // types not part of Java language? - !klass1->is_java_klass()) { // types not part of Java language? + if (klass0->equals(klass1)) { // if types are unequal but klasses are equal // Do nothing; we know nothing for imprecise types } else if (klass0->is_subtype_of(klass1)) { // If klass1's type is PRECISE, then classes are unrelated. @@ -744,7 +742,7 @@ static inline Node* isa_const_java_mirror(PhaseGVN* phase, Node* n) { } // return the ConP(Foo.klass) - assert(mirror_type->is_klass(), "mirror_type should represent a klassOop"); + assert(mirror_type->is_klass(), "mirror_type should represent a Klass*"); return phase->makecon(TypeKlassPtr::make(mirror_type->as_klass())); } @@ -891,9 +889,7 @@ const Type *CmpNNode::sub( const Type *t1, const Type *t2 ) const { // See if neither subclasses the other, or if the class on top // is precise. In either of these cases, the compare is known // to fail if at least one of the pointers is provably not null. - if (klass0->equals(klass1) || // if types are unequal but klasses are - !klass0->is_java_klass() || // types not part of Java language? - !klass1->is_java_klass()) { // types not part of Java language? + if (klass0->equals(klass1)) { // if types are unequal but klasses are equal // Do nothing; we know nothing for imprecise types } else if (klass0->is_subtype_of(klass1)) { // If klass1's type is PRECISE, then classes are unrelated. diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp index 80d583042..7ce52ce32 100644 --- a/src/share/vm/opto/type.cpp +++ b/src/share/vm/opto/type.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "ci/ciMethodData.hpp" #include "ci/ciTypeFlow.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" @@ -33,7 +34,6 @@ #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" -#include "oops/klassKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/typeArrayKlass.hpp" #include "opto/matcher.hpp" @@ -49,40 +49,46 @@ Dict* Type::_shared_type_dict = NULL; // Array which maps compiler types to Basic Types -const BasicType Type::_basic_type[Type::lastype] = { - T_ILLEGAL, // Bad - T_ILLEGAL, // Control - T_VOID, // Top - T_INT, // Int - T_LONG, // Long - T_VOID, // Half - T_NARROWOOP, // NarrowOop - - T_ILLEGAL, // Tuple - T_ARRAY, // Array - T_ILLEGAL, // VectorS - T_ILLEGAL, // VectorD - T_ILLEGAL, // VectorX - T_ILLEGAL, // VectorY - - T_ADDRESS, // AnyPtr // shows up in factory methods for NULL_PTR - T_ADDRESS, // RawPtr - T_OBJECT, // OopPtr - T_OBJECT, // InstPtr - T_OBJECT, // AryPtr - T_OBJECT, // KlassPtr - - T_OBJECT, // Function - T_ILLEGAL, // Abio - T_ADDRESS, // Return_Address - T_ILLEGAL, // Memory - T_FLOAT, // FloatTop - T_FLOAT, // FloatCon - T_FLOAT, // FloatBot - T_DOUBLE, // DoubleTop - T_DOUBLE, // DoubleCon - T_DOUBLE, // DoubleBot - T_ILLEGAL, // Bottom +Type::TypeInfo Type::_type_info[Type::lastype] = { + { Bad, T_ILLEGAL, "bad", false, Node::NotAMachineReg, relocInfo::none }, // Bad + { Control, T_ILLEGAL, "control", false, 0, relocInfo::none }, // Control + { Bottom, T_VOID, "top", false, 0, relocInfo::none }, // Top + { Bad, T_INT, "int:", false, Op_RegI, relocInfo::none }, // Int + { Bad, T_LONG, "long:", false, Op_RegL, relocInfo::none }, // Long + { Half, T_VOID, "half", false, 0, relocInfo::none }, // Half + { Bad, T_NARROWOOP, "narrowoop:", false, Op_RegN, relocInfo::none }, // NarrowOop + { Bad, T_ILLEGAL, "tuple:", false, Node::NotAMachineReg, relocInfo::none }, // Tuple + { Bad, T_ARRAY, "array:", false, Node::NotAMachineReg, relocInfo::none }, // Array + +#if defined(IA32) || defined(AMD64) + { Bad, T_ILLEGAL, "vectors:", false, Op_VecS, relocInfo::none }, // VectorS + { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD + { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX + { Bad, T_ILLEGAL, "vectory:", false, Op_VecY, relocInfo::none }, // VectorY +#else + { Bad, T_ILLEGAL, "vectors:", false, 0, relocInfo::none }, // VectorS + { Bad, T_ILLEGAL, "vectord:", false, Op_RegD, relocInfo::none }, // VectorD + { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX + { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY +#endif // IA32 || AMD64 + { Bad, T_ADDRESS, "anyptr:", false, Op_RegP, relocInfo::none }, // AnyPtr + { Bad, T_ADDRESS, "rawptr:", false, Op_RegP, relocInfo::none }, // RawPtr + { Bad, T_OBJECT, "oop:", true, Op_RegP, relocInfo::oop_type }, // OopPtr + { Bad, T_OBJECT, "inst:", true, Op_RegP, relocInfo::oop_type }, // InstPtr + { Bad, T_OBJECT, "ary:", true, Op_RegP, relocInfo::oop_type }, // AryPtr + { Bad, T_METADATA, "metadata:", false, Op_RegP, relocInfo::metadata_type }, // MetadataPtr + { Bad, T_METADATA, "klass:", false, Op_RegP, relocInfo::metadata_type }, // KlassPtr + { Bad, T_OBJECT, "func", false, 0, relocInfo::none }, // Function + { Abio, T_ILLEGAL, "abIO", false, 0, relocInfo::none }, // Abio + { Return_Address, T_ADDRESS, "return_address",false, Op_RegP, relocInfo::none }, // Return_Address + { Memory, T_ILLEGAL, "memory", false, 0, relocInfo::none }, // Memory + { FloatBot, T_FLOAT, "float_top", false, Op_RegF, relocInfo::none }, // FloatTop + { FloatCon, T_FLOAT, "ftcon:", false, Op_RegF, relocInfo::none }, // FloatCon + { FloatTop, T_FLOAT, "float", false, Op_RegF, relocInfo::none }, // FloatBot + { DoubleBot, T_DOUBLE, "double_top", false, Op_RegD, relocInfo::none }, // DoubleTop + { DoubleCon, T_DOUBLE, "dblcon:", false, Op_RegD, relocInfo::none }, // DoubleCon + { DoubleTop, T_DOUBLE, "double", false, Op_RegD, relocInfo::none }, // DoubleBot + { Top, T_ILLEGAL, "bottom", false, 0, relocInfo::none } // Bottom }; // Map ideal registers (machine types) to ideal types @@ -321,6 +327,8 @@ void Type::Initialize_shared(Compile* current) { false, 0, oopDesc::klass_offset_in_bytes()); TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot); + TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot); + TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR ); TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM ); @@ -340,6 +348,7 @@ void Type::Initialize_shared(Compile* current) { #ifdef _LP64 if (UseCompressedOops) { + assert(TypeAryPtr::NARROWOOPS->is_ptr_to_narrowoop(), "array of narrow oops must be ptr to narrow oop"); TypeAryPtr::OOPS = TypeAryPtr::NARROWOOPS; } else #endif @@ -372,7 +381,7 @@ void Type::Initialize_shared(Compile* current) { TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make( TypePtr::BotPTR, current->env()->Object_klass(), 0 ); const Type **fi2c = TypeTuple::fields(2); - fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // methodOop + fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // Method* fi2c[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // argument pointer TypeTuple::START_I2C = TypeTuple::make(TypeFunc::Parms+2, fi2c); @@ -461,10 +470,6 @@ void Type::Initialize(Compile* current) { Type* t = (Type*)i._value; tdic->Insert(t,t); // New Type, insert into Type table } - -#ifdef ASSERT - verify_lastype(); -#endif } //------------------------------hashcons--------------------------------------- @@ -620,6 +625,7 @@ const Type *Type::xmeet( const Type *t ) const { case InstPtr: return t->xmeet(this); + case MetadataPtr: case KlassPtr: return t->xmeet(this); @@ -700,6 +706,8 @@ const Type::TYPES Type::dual_type[Type::lastype] = { Bad, // OopPtr - handled in v-call Bad, // InstPtr - handled in v-call Bad, // AryPtr - handled in v-call + + Bad, // MetadataPtr - handled in v-call Bad, // KlassPtr - handled in v-call Bad, // Function - handled in v-call @@ -717,8 +725,8 @@ const Type::TYPES Type::dual_type[Type::lastype] = { const Type *Type::xdual() const { // Note: the base() accessor asserts the sanity of _base. - assert(dual_type[base()] != Bad, "implement with v-call"); - return new Type(dual_type[_base]); + assert(_type_info[base()].dual_type != Bad, "implement with v-call"); + return new Type(_type_info[_base].dual_type); } //------------------------------has_memory------------------------------------- @@ -738,7 +746,7 @@ bool Type::has_memory() const { #ifndef PRODUCT //------------------------------dump2------------------------------------------ void Type::dump2( Dict &d, uint depth, outputStream *st ) const { - st->print(msg[_base]); + st->print(_type_info[_base].msg); } //------------------------------dump------------------------------------------- @@ -750,17 +758,6 @@ void Type::dump_on(outputStream *st) const { st->print(" [narrow]"); } } - -//------------------------------data------------------------------------------- -const char * const Type::msg[Type::lastype] = { - "bad","control","top","int:","long:","half", "narrowoop:", - "tuple:", "array:", "vectors:", "vectord:", "vectorx:", "vectory:", - "anyptr:", "rawptr:", "java:", "inst:", "aryptr:", "klass:", - "func", "abIO", "return_address", "memory", - "float_top", "ftcon:", "float", - "double_top", "dblcon:", "double", - "bottom" -}; #endif //------------------------------singleton-------------------------------------- @@ -813,31 +810,6 @@ void Type::typerr( const Type *t ) const { ShouldNotReachHere(); } -//------------------------------isa_oop_ptr------------------------------------ -// Return true if type is an oop pointer type. False for raw pointers. -static char isa_oop_ptr_tbl[Type::lastype] = { - 0,0,0,0,0,0,0/*narrowoop*/,0/*tuple*/, 0/*array*/, 0, 0, 0, 0/*vector*/, - 0/*anyptr*/,0/*rawptr*/,1/*OopPtr*/,1/*InstPtr*/,1/*AryPtr*/,1/*KlassPtr*/, - 0/*func*/,0,0/*return_address*/,0, - /*floats*/0,0,0, /*doubles*/0,0,0, - 0 -}; -bool Type::isa_oop_ptr() const { - return isa_oop_ptr_tbl[_base] != 0; -} - -//------------------------------dump_stats------------------------------------- -// // Check that arrays match type enum -#ifndef PRODUCT -void Type::verify_lastype() { - // Check that arrays match enumeration - assert( Type::dual_type [Type::lastype - 1] == Type::Top, "did not update array"); - assert( strcmp(Type::msg [Type::lastype - 1],"bottom") == 0, "did not update array"); - // assert( PhiNode::tbl [Type::lastype - 1] == NULL, "did not update array"); - assert( Matcher::base2reg[Type::lastype - 1] == 0, "did not update array"); - assert( isa_oop_ptr_tbl [Type::lastype - 1] == (char)0, "did not update array"); -} -#endif //============================================================================= // Convenience common pre-built types. @@ -862,8 +834,9 @@ const Type *TypeF::xmeet( const Type *t ) const { case RawPtr: // reuses local variables case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: case NarrowOop: case Int: case Long: @@ -978,8 +951,9 @@ const Type *TypeD::xmeet( const Type *t ) const { case RawPtr: // reuses local variables case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: case NarrowOop: case Int: case Long: @@ -1131,8 +1105,9 @@ const Type *TypeInt::xmeet( const Type *t ) const { case RawPtr: // reuses local variables case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: case NarrowOop: case Long: case FloatTop: @@ -1387,8 +1362,9 @@ const Type *TypeLong::xmeet( const Type *t ) const { case RawPtr: // reuses local variables case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: case NarrowOop: case Int: case FloatTop: @@ -2132,8 +2108,9 @@ const Type *TypePtr::xmeet( const Type *t ) const { case RawPtr: // For these, flip the call around to cut down case OopPtr: case InstPtr: // on the cases I have to handle. - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: return t->xmeet(this); // Call in reverse direction default: // All else is a mistake typerr(t); @@ -2288,8 +2265,9 @@ const Type *TypeRawPtr::xmeet( const Type *t ) const { case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: return TypePtr::BOTTOM; // Oop meet raw is not well defined default: // All else is a mistake typerr(t); @@ -2375,11 +2353,12 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int _instance_id(instance_id) { #ifdef _LP64 if (UseCompressedOops && _offset != 0) { - if (klass() == NULL) { + if (_offset == oopDesc::klass_offset_in_bytes()) { + _is_ptr_to_narrowoop = UseCompressedKlassPointers; + } else if (klass() == NULL) { + // Array with unknown body type assert(this->isa_aryptr(), "only arrays without klass"); _is_ptr_to_narrowoop = true; - } else if (_offset == oopDesc::klass_offset_in_bytes()) { - _is_ptr_to_narrowoop = true; } else if (this->isa_aryptr()) { _is_ptr_to_narrowoop = (klass()->is_obj_array_klass() && _offset != arrayOopDesc::length_offset_in_bytes()); @@ -2399,7 +2378,7 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int _offset == java_lang_Class::array_klass_offset_in_bytes())) { // Special hidden fields from the Class. assert(this->isa_instptr(), "must be an instance ptr."); - _is_ptr_to_narrowoop = true; + _is_ptr_to_narrowoop = false; } else if (klass() == ciEnv::current()->Class_klass() && _offset >= instanceMirrorKlass::offset_of_static_fields()) { // Static fields @@ -2423,7 +2402,6 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int _is_ptr_to_narrowoop = true; } else { // Type for the copy start in LibraryCallKit::inline_native_clone(). - assert(!klass_is_exact(), "only non-exact klass"); _is_ptr_to_narrowoop = true; } } @@ -2437,7 +2415,7 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int const TypeOopPtr *TypeOopPtr::make(PTR ptr, int offset, int instance_id) { assert(ptr != Constant, "no constant generic pointers"); - ciKlass* k = ciKlassKlass::make(); + ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; ciObject* o = NULL; return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons(); @@ -2472,7 +2450,7 @@ const Type *TypeOopPtr::cast_to_exactness(bool klass_is_exact) const { const TypeKlassPtr* TypeOopPtr::as_klass_type() const { ciKlass* k = klass(); bool xk = klass_is_exact(); - if (k == NULL || !k->is_java_klass()) + if (k == NULL) return TypeKlassPtr::OBJECT; else return TypeKlassPtr::make(xk? Constant: NotNull, k, 0); @@ -2506,6 +2484,8 @@ const Type *TypeOopPtr::xmeet( const Type *t ) const { typerr(t); case RawPtr: + case MetadataPtr: + case KlassPtr: return TypePtr::BOTTOM; // Oop meet raw is not well defined case AnyPtr: { @@ -2536,7 +2516,6 @@ const Type *TypeOopPtr::xmeet( const Type *t ) const { } case InstPtr: // For these, flip the call around to cut down - case KlassPtr: // on the cases I have to handle. case AryPtr: return t->xmeet(this); // Call in reverse direction @@ -2548,7 +2527,7 @@ const Type *TypeOopPtr::xmeet( const Type *t ) const { //------------------------------xdual------------------------------------------ // Dual of a pure heap pointer. No relevant klass or oop information. const Type *TypeOopPtr::xdual() const { - assert(klass() == ciKlassKlass::make(), "no klasses here"); + assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); assert(const_oop() == NULL, "no constants here"); return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() ); } @@ -2556,7 +2535,6 @@ const Type *TypeOopPtr::xdual() const { //--------------------------make_from_klass_common----------------------------- // Computes the element-type given a klass. const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_change, bool try_for_exact) { - assert(klass->is_java_klass(), "must be java language klass"); if (klass->is_instance_klass()) { Compile* C = Compile::current(); Dependencies* deps = C->dependencies(); @@ -2613,24 +2591,6 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ //------------------------------make_from_constant----------------------------- // Make a java pointer from an oop constant const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) { - if (o->is_method_data() || o->is_method()) { - // Treat much like a typeArray of bytes, like below, but fake the type... - const BasicType bt = T_BYTE; - const Type* etype = get_const_basic_type(bt); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); - ciKlass* klass = ciArrayKlass::make(ciType::make(bt)); - assert(o->can_be_constant(), "should be tenured"); - return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); - } else if (o->is_cpcache()) { - // Treat much like a objArray, like below, but fake the type... - const BasicType bt = T_OBJECT; - const Type* etype = get_const_basic_type(bt); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); - ciKlass* klass = ciArrayKlass::make(ciType::make(bt)); - assert(o->can_be_constant(), "should be tenured"); - return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); - } else { - assert(o->is_java_object(), "must be java language object"); assert(!o->is_null_object(), "null object not yet handled here."); ciKlass* klass = o->klass(); if (klass->is_instance_klass()) { @@ -2643,7 +2603,8 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_const return TypeInstPtr::make(o); } else if (klass->is_obj_array_klass()) { // Element is an object array. Recursively call ourself. - const Type *etype = make_from_klass_raw(klass->as_obj_array_klass()->element_klass()); + const Type *etype = + TypeOopPtr::make_from_klass_raw(klass->as_obj_array_klass()->element_klass()); const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); // We used to pass NotNull in here, asserting that the sub-arrays // are all not-null. This is not true in generally, as code can @@ -2653,10 +2614,12 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_const } else if (!o->should_be_constant()) { return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } - return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); + return arr; } else if (klass->is_type_array_klass()) { // Element is an typeArray - const Type* etype = get_const_basic_type(klass->as_type_array_klass()->element_type()); + const Type* etype = + (Type*)get_const_basic_type(klass->as_type_array_klass()->element_type()); const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length())); // We used to pass NotNull in here, asserting that the array pointer // is not-null. That was not true in general. @@ -2665,8 +2628,8 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_const } else if (!o->should_be_constant()) { return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } - return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); - } + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); + return arr; } fatal("unhandled object type"); @@ -2845,8 +2808,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, ciObject* o, int offset, int instance_id) { - assert( !k->is_loaded() || k->is_instance_klass() || - k->is_method_klass(), "Must be for instance or method"); + assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant assert( (!o && ptr != Constant) || (o && ptr == Constant), "constant pointers must have a value supplied" ); @@ -2971,6 +2933,8 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { default: // All else is a mistake typerr(t); + case MetadataPtr: + case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // All arrays inherit from Object class @@ -3237,9 +3201,6 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { return make( ptr, k, false, NULL, off, instance_id ); } // End of case InstPtr - case KlassPtr: - return TypeInstPtr::BOTTOM; - } // End of switch return this; // Return the double constant } @@ -3516,6 +3477,8 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { } } + case MetadataPtr: + case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // Meeting 2 references? @@ -3634,10 +3597,6 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { default: typerr(t); } } - - case KlassPtr: - return TypeInstPtr::BOTTOM; - } return this; // Lint noise } @@ -3768,8 +3727,9 @@ const Type *TypeNarrowOop::xmeet( const Type *t ) const { case RawPtr: case OopPtr: case InstPtr: - case KlassPtr: case AryPtr: + case MetadataPtr: + case KlassPtr: case Bottom: // Ye Olde Default return Type::BOTTOM; @@ -3829,6 +3789,183 @@ void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { #endif + +//------------------------------eq--------------------------------------------- +// Structural equality check for Type representations +bool TypeMetadataPtr::eq( const Type *t ) const { + const TypeMetadataPtr *a = (const TypeMetadataPtr*)t; + ciMetadata* one = metadata(); + ciMetadata* two = a->metadata(); + if (one == NULL || two == NULL) { + return (one == two) && TypePtr::eq(t); + } else { + return one->equals(two) && TypePtr::eq(t); + } +} + +//------------------------------hash------------------------------------------- +// Type-specific hashing function. +int TypeMetadataPtr::hash(void) const { + return + (metadata() ? metadata()->hash() : 0) + + TypePtr::hash(); +} + +//------------------------------singleton-------------------------------------- +// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple +// constants +bool TypeMetadataPtr::singleton(void) const { + // detune optimizer to not generate constant metadta + constant offset as a constant! + // TopPTR, Null, AnyNull, Constant are all singletons + return (_offset == 0) && !below_centerline(_ptr); +} + +//------------------------------add_offset------------------------------------- +const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const { + return make( _ptr, _metadata, xadd_offset(offset)); +} + +//-----------------------------filter------------------------------------------ +// Do not allow interface-vs.-noninterface joins to collapse to top. +const Type *TypeMetadataPtr::filter( const Type *kills ) const { + const TypeMetadataPtr* ft = join(kills)->isa_metadataptr(); + if (ft == NULL || ft->empty()) + return Type::TOP; // Canonical empty value + return ft; +} + + //------------------------------get_con---------------------------------------- +intptr_t TypeMetadataPtr::get_con() const { + assert( _ptr == Null || _ptr == Constant, "" ); + assert( _offset >= 0, "" ); + + if (_offset != 0) { + // After being ported to the compiler interface, the compiler no longer + // directly manipulates the addresses of oops. Rather, it only has a pointer + // to a handle at compile time. This handle is embedded in the generated + // code and dereferenced at the time the nmethod is made. Until that time, + // it is not reasonable to do arithmetic with the addresses of oops (we don't + // have access to the addresses!). This does not seem to currently happen, + // but this assertion here is to help prevent its occurence. + tty->print_cr("Found oop constant with non-zero offset"); + ShouldNotReachHere(); + } + + return (intptr_t)metadata()->constant_encoding(); +} + +//------------------------------cast_to_ptr_type------------------------------- +const Type *TypeMetadataPtr::cast_to_ptr_type(PTR ptr) const { + if( ptr == _ptr ) return this; + return make(ptr, metadata(), _offset); +} + +//------------------------------meet------------------------------------------- +// Compute the MEET of two types. It returns a new Type object. +const Type *TypeMetadataPtr::xmeet( const Type *t ) const { + // Perform a fast test for common case; meeting the same types together. + if( this == t ) return this; // Meeting same type-rep? + + // Current "this->_base" is OopPtr + switch (t->base()) { // switch on original type + + case Int: // Mixing ints & oops happens when javac + case Long: // reuses local variables + case FloatTop: + case FloatCon: + case FloatBot: + case DoubleTop: + case DoubleCon: + case DoubleBot: + case NarrowOop: + case Bottom: // Ye Olde Default + return Type::BOTTOM; + case Top: + return this; + + default: // All else is a mistake + typerr(t); + + case AnyPtr: { + // Found an AnyPtr type vs self-OopPtr type + const TypePtr *tp = t->is_ptr(); + int offset = meet_offset(tp->offset()); + PTR ptr = meet_ptr(tp->ptr()); + switch (tp->ptr()) { + case Null: + if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset); + // else fall through: + case TopPTR: + case AnyNull: { + return make(ptr, NULL, offset); + } + case BotPTR: + case NotNull: + return TypePtr::make(AnyPtr, ptr, offset); + default: typerr(t); + } + } + + case RawPtr: + case KlassPtr: + case OopPtr: + case InstPtr: + case AryPtr: + return TypePtr::BOTTOM; // Oop meet raw is not well defined + + case MetadataPtr: + ShouldNotReachHere(); + break; + + } // End of switch + return this; // Return the double constant +} + + +//------------------------------xdual------------------------------------------ +// Dual of a pure metadata pointer. +const Type *TypeMetadataPtr::xdual() const { + return new TypeMetadataPtr(dual_ptr(), metadata(), dual_offset()); +} + +//------------------------------dump2------------------------------------------ +#ifndef PRODUCT +void TypeMetadataPtr::dump2( Dict &d, uint depth, outputStream *st ) const { + st->print("metadataptr:%s", ptr_msg[_ptr]); + if( metadata() ) st->print(INTPTR_FORMAT, metadata()); + switch( _offset ) { + case OffsetTop: st->print("+top"); break; + case OffsetBot: st->print("+any"); break; + case 0: break; + default: st->print("+%d",_offset); break; + } +} +#endif + + +//============================================================================= +// Convenience common pre-built type. +const TypeMetadataPtr *TypeMetadataPtr::BOTTOM; + +TypeMetadataPtr::TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset): + TypePtr(MetadataPtr, ptr, offset), _metadata(metadata) { +} + +const TypeMetadataPtr* TypeMetadataPtr::make(ciMethod* m) { + return make(Constant, m, 0); +} +const TypeMetadataPtr* TypeMetadataPtr::make(ciMethodData* m) { + return make(Constant, m, 0); +} + +//------------------------------make------------------------------------------- +// Create a meta data constant +const TypeMetadataPtr *TypeMetadataPtr::make(PTR ptr, ciMetadata* m, int offset) { + assert(m == NULL || !m->is_klass(), "wrong type"); + return (TypeMetadataPtr*)(new TypeMetadataPtr(ptr, m, offset))->hashcons(); +} + + //============================================================================= // Convenience common pre-built types. @@ -3836,17 +3973,16 @@ void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { const TypeKlassPtr *TypeKlassPtr::OBJECT; const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL; -//------------------------------TypeKlasPtr------------------------------------ +//------------------------------TypeKlassPtr----------------------------------- TypeKlassPtr::TypeKlassPtr( PTR ptr, ciKlass* klass, int offset ) - : TypeOopPtr(KlassPtr, ptr, klass, (ptr==Constant), (ptr==Constant ? klass : NULL), offset, 0) { + : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant) { } //------------------------------make------------------------------------------- // ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant const TypeKlassPtr *TypeKlassPtr::make( PTR ptr, ciKlass* k, int offset ) { assert( k != NULL, "Expect a non-NULL klass"); - assert(k->is_instance_klass() || k->is_array_klass() || - k->is_method_klass(), "Incorrect type of klass oop"); + assert(k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop"); TypeKlassPtr *r = (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset))->hashcons(); @@ -3859,15 +3995,23 @@ bool TypeKlassPtr::eq( const Type *t ) const { const TypeKlassPtr *p = t->is_klassptr(); return klass()->equals(p->klass()) && - TypeOopPtr::eq(p); + TypePtr::eq(p); } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeKlassPtr::hash(void) const { - return klass()->hash() + TypeOopPtr::hash(); + return klass()->hash() + TypePtr::hash(); } +//------------------------------singleton-------------------------------------- +// TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple +// constants +bool TypeKlassPtr::singleton(void) const { + // detune optimizer to not generate constant klass + constant offset as a constant! + // TopPTR, Null, AnyNull, Constant are all singletons + return (_offset == 0) && !below_centerline(_ptr); +} //----------------------compute_klass------------------------------------------ // Compute the defining klass for this class @@ -4018,24 +4162,6 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { default: // All else is a mistake typerr(t); - case RawPtr: return TypePtr::BOTTOM; - - case OopPtr: { // Meeting to OopPtrs - // Found a OopPtr type vs self-KlassPtr type - const TypePtr *tp = t->is_oopptr(); - int offset = meet_offset(tp->offset()); - PTR ptr = meet_ptr(tp->ptr()); - switch (tp->ptr()) { - case TopPTR: - case AnyNull: - return make(ptr, klass(), offset); - case BotPTR: - case NotNull: - return TypePtr::make(AnyPtr, ptr, offset); - default: typerr(t); - } - } - case AnyPtr: { // Meeting to AnyPtrs // Found an AnyPtr type vs self-KlassPtr type const TypePtr *tp = t->is_ptr(); @@ -4055,9 +4181,12 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { } } + case RawPtr: + case MetadataPtr: + case OopPtr: case AryPtr: // Meet with AryPtr case InstPtr: // Meet with InstPtr - return TypeInstPtr::BOTTOM; + return TypePtr::BOTTOM; // // A-top } @@ -4112,17 +4241,11 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { // If the klasses are equal, the constants may still differ. Fall to // NotNull if they do (neither constant is NULL; that is a special case // handled elsewhere). - ciObject* o = NULL; // Assume not constant when done - ciObject* this_oop = const_oop(); - ciObject* tkls_oop = tkls->const_oop(); if( ptr == Constant ) { - if (this_oop != NULL && tkls_oop != NULL && - this_oop->equals(tkls_oop) ) - o = this_oop; - else if (above_centerline(this->ptr())) - o = tkls_oop; - else if (above_centerline(tkls->ptr())) - o = this_oop; + if (this->_ptr == Constant && tkls->_ptr == Constant && + this->klass()->equals(tkls->klass())); + else if (above_centerline(this->ptr())); + else if (above_centerline(tkls->ptr())); else ptr = NotNull; } @@ -4148,6 +4271,25 @@ const Type *TypeKlassPtr::xdual() const { return new TypeKlassPtr( dual_ptr(), klass(), dual_offset() ); } +//------------------------------get_con---------------------------------------- +intptr_t TypeKlassPtr::get_con() const { + assert( _ptr == Null || _ptr == Constant, "" ); + assert( _offset >= 0, "" ); + + if (_offset != 0) { + // After being ported to the compiler interface, the compiler no longer + // directly manipulates the addresses of oops. Rather, it only has a pointer + // to a handle at compile time. This handle is embedded in the generated + // code and dereferenced at the time the nmethod is made. Until that time, + // it is not reasonable to do arithmetic with the addresses of oops (we don't + // have access to the addresses!). This does not seem to currently happen, + // but this assertion here is to help prevent its occurence. + tty->print_cr("Found oop constant with non-zero offset"); + ShouldNotReachHere(); + } + + return (intptr_t)klass()->constant_encoding(); +} //------------------------------dump2------------------------------------------ // Dump Klass Type #ifndef PRODUCT @@ -4280,35 +4422,6 @@ void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { } st->print(" )"); } - -//------------------------------print_flattened-------------------------------- -// Print a 'flattened' signature -static const char * const flat_type_msg[Type::lastype] = { - "bad","control","top","int","long","_", "narrowoop", - "tuple:", "array:", "vectors:", "vectord:", "vectorx:", "vectory:", - "ptr", "rawptr", "ptr", "ptr", "ptr", "ptr", - "func", "abIO", "return_address", "mem", - "float_top", "ftcon:", "flt", - "double_top", "dblcon:", "dbl", - "bottom" -}; - -void TypeFunc::print_flattened() const { - if( _range->_cnt <= Parms ) - tty->print("void"); - else { - uint i; - for (i = Parms; i < _range->_cnt-1; i++) - tty->print("%s/",flat_type_msg[_range->field_at(i)->base()]); - tty->print("%s",flat_type_msg[_range->field_at(i)->base()]); - } - tty->print(" ( "); - if (Parms < _domain->_cnt) - tty->print("%s",flat_type_msg[_domain->field_at(Parms)->base()]); - for (uint i = Parms+1; i < _domain->_cnt; i++) - tty->print(", %s",flat_type_msg[_domain->field_at(i)->base()]); - tty->print(" )"); -} #endif //------------------------------singleton-------------------------------------- diff --git a/src/share/vm/opto/type.hpp b/src/share/vm/opto/type.hpp index a4b5487d7..666c78f5c 100644 --- a/src/share/vm/opto/type.hpp +++ b/src/share/vm/opto/type.hpp @@ -62,6 +62,7 @@ class TypeOopPtr; class TypeInstPtr; class TypeAryPtr; class TypeKlassPtr; +class TypeMetadataPtr; //------------------------------Type------------------------------------------- // Basic Type object, represents a set of primitive Values. @@ -93,9 +94,11 @@ public: OopPtr, // Any and all Java heap entities InstPtr, // Instance pointers (non-array objects) AryPtr, // Array pointers - KlassPtr, // Klass pointers // (Ptr order matters: See is_ptr, isa_ptr, is_oopptr, isa_oopptr.) + MetadataPtr, // Generic metadata + KlassPtr, // Klass pointers + Function, // Function signature Abio, // Abstract I/O Return_Address, // Subroutine return address @@ -123,8 +126,18 @@ public: }; private: + typedef struct { + const TYPES dual_type; + const BasicType basic_type; + const char* msg; + const bool isa_oop; + const int ideal_reg; + const relocInfo::relocType reloc; + } TypeInfo; + // Dictionary of types shared among compilations. static Dict* _shared_type_dict; + static TypeInfo _type_info[]; static int uhash( const Type *const t ); // Structural equality check. Assumes that cmp() has already compared @@ -241,12 +254,16 @@ public: const TypeNarrowOop *isa_narrowoop() const; // Returns NULL if not oop ptr type const TypeOopPtr *isa_oopptr() const; // Returns NULL if not oop ptr type const TypeOopPtr *is_oopptr() const; // Java-style GC'd pointer - const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr - const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr const TypeInstPtr *isa_instptr() const; // Returns NULL if not InstPtr const TypeInstPtr *is_instptr() const; // Instance const TypeAryPtr *isa_aryptr() const; // Returns NULL if not AryPtr const TypeAryPtr *is_aryptr() const; // Array oop + + const TypeMetadataPtr *isa_metadataptr() const; // Returns NULL if not oop ptr type + const TypeMetadataPtr *is_metadataptr() const; // Java-style GC'd pointer + const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr + const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr + virtual bool is_finite() const; // Has a finite value virtual bool is_nan() const; // Is not a number (NaN) @@ -267,9 +284,6 @@ public: // Do you have memory, directly or through a tuple? bool has_memory( ) const; - // Are you a pointer type or not? - bool isa_oop_ptr() const; - // TRUE if type is a singleton virtual bool singleton(void) const; @@ -284,7 +298,6 @@ public: static const Type *mreg2type[]; // Printing, statistics - static const char * const msg[lastype]; // Printable strings #ifndef PRODUCT void dump_on(outputStream *st) const; void dump() const { @@ -292,7 +305,6 @@ public: } virtual void dump2( Dict &d, uint depth, outputStream *st ) const; static void dump_stats(); - static void verify_lastype(); // Check that arrays match type enum #endif void typerr(const Type *t) const; // Mixing types error @@ -336,7 +348,11 @@ public: static const Type *TOP; // Mapping from compiler type to VM BasicType - BasicType basic_type() const { return _basic_type[_base]; } + BasicType basic_type() const { return _type_info[_base].basic_type; } + int ideal_reg() const { return _type_info[_base].ideal_reg; } + const char* msg() const { return _type_info[_base].msg; } + bool isa_oop_ptr() const { return _type_info[_base].isa_oop; } + relocInfo::relocType reloc() const { return _type_info[_base].reloc; } // Mapping from CI type system to compiler type: static const Type* get_typeflow_type(ciType* type); @@ -842,7 +858,7 @@ public: //------------------------------TypeInstPtr------------------------------------ // Class of Java object pointers, pointing either to non-array Java instances -// or to a klassOop (including array klasses). +// or to a Klass* (including array klasses). class TypeInstPtr : public TypeOopPtr { TypeInstPtr( PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id ); virtual bool eq( const Type *t ) const; @@ -859,7 +875,6 @@ class TypeInstPtr : public TypeOopPtr { static const TypeInstPtr *make(ciObject* o) { return make(TypePtr::Constant, o->klass(), true, o, 0); } - // Make a pointer to a constant oop with offset. static const TypeInstPtr *make(ciObject* o, int offset) { return make(TypePtr::Constant, o->klass(), true, o, offset); @@ -992,18 +1007,92 @@ public: #endif }; +//------------------------------TypeMetadataPtr------------------------------------- +// Some kind of metadata, either Method*, MethodData* or CPCacheOop +class TypeMetadataPtr : public TypePtr { +protected: + TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset); +public: + virtual bool eq( const Type *t ) const; + virtual int hash() const; // Type specific hashing + virtual bool singleton(void) const; // TRUE if type is a singleton + +private: + ciMetadata* _metadata; + +public: + static const TypeMetadataPtr* make(PTR ptr, ciMetadata* m, int offset); + + static const TypeMetadataPtr* make(ciMethod* m); + static const TypeMetadataPtr* make(ciMethodData* m); + + ciMetadata* metadata() const { return _metadata; } + + virtual const Type *cast_to_ptr_type(PTR ptr) const; + + virtual const TypePtr *add_offset( intptr_t offset ) const; + + virtual const Type *xmeet( const Type *t ) const; + virtual const Type *xdual() const; // Compute dual right now. + + virtual intptr_t get_con() const; + + // Do not allow interface-vs.-noninterface joins to collapse to top. + virtual const Type *filter( const Type *kills ) const; + + // Convenience common pre-built types. + static const TypeMetadataPtr *BOTTOM; + +#ifndef PRODUCT + virtual void dump2( Dict &d, uint depth, outputStream *st ) const; +#endif +}; + //------------------------------TypeKlassPtr----------------------------------- // Class of Java Klass pointers -class TypeKlassPtr : public TypeOopPtr { +class TypeKlassPtr : public TypePtr { TypeKlassPtr( PTR ptr, ciKlass* klass, int offset ); + public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing + virtual bool singleton(void) const; // TRUE if type is a singleton + private: + + static const TypeKlassPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); + + ciKlass* _klass; + + // Does the type exclude subclasses of the klass? (Inexact == polymorphic.) + bool _klass_is_exact; public: - ciSymbol* name() const { return _klass->name(); } + ciSymbol* name() const { return klass()->name(); } - bool is_loaded() const { return _klass->is_loaded(); } + ciKlass* klass() const { return _klass; } + bool klass_is_exact() const { return _klass_is_exact; } + + bool is_loaded() const { return klass()->is_loaded(); } + + // Creates a type given a klass. Correctly handles multi-dimensional arrays + // Respects UseUniqueSubclasses. + // If the klass is final, the resulting type will be exact. + static const TypeKlassPtr* make_from_klass(ciKlass* klass) { + return make_from_klass_common(klass, true, false); + } + // Same as before, but will produce an exact type, even if + // the klass is not final, as long as it has exactly one implementation. + static const TypeKlassPtr* make_from_klass_unique(ciKlass* klass) { + return make_from_klass_common(klass, true, true); + } + // Same as before, but does not respects UseUniqueSubclasses. + // Use this only for creating array element types. + static const TypeKlassPtr* make_from_klass_raw(ciKlass* klass) { + return make_from_klass_common(klass, false, false); + } + + // Make a generic (unclassed) pointer to metadata. + static const TypeKlassPtr* make(PTR ptr, int offset); // ptr to klass 'k' static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); } @@ -1023,6 +1112,8 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. + virtual intptr_t get_con() const; + // Convenience common pre-built types. static const TypeKlassPtr* OBJECT; // Not-null object klass or below static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same @@ -1117,7 +1208,6 @@ public: #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping - void print_flattened() const; // Print a 'flattened' signature #endif // Convenience common pre-built types. }; @@ -1209,13 +1299,13 @@ inline const TypePtr *Type::isa_ptr() const { inline const TypeOopPtr *Type::is_oopptr() const { // OopPtr is the first and KlassPtr the last, with no non-oops between. - assert(_base >= OopPtr && _base <= KlassPtr, "Not a Java pointer" ) ; + assert(_base >= OopPtr && _base <= AryPtr, "Not a Java pointer" ) ; return (TypeOopPtr*)this; } inline const TypeOopPtr *Type::isa_oopptr() const { // OopPtr is the first and KlassPtr the last, with no non-oops between. - return (_base >= OopPtr && _base <= KlassPtr) ? (TypeOopPtr*)this : NULL; + return (_base >= OopPtr && _base <= AryPtr) ? (TypeOopPtr*)this : NULL; } inline const TypeRawPtr *Type::isa_rawptr() const { @@ -1256,6 +1346,16 @@ inline const TypeNarrowOop *Type::isa_narrowoop() const { return (_base == NarrowOop) ? (TypeNarrowOop*)this : NULL; } +inline const TypeMetadataPtr *Type::is_metadataptr() const { + // MetadataPtr is the first and CPCachePtr the last + assert(_base == MetadataPtr, "Not a metadata pointer" ) ; + return (TypeMetadataPtr*)this; +} + +inline const TypeMetadataPtr *Type::isa_metadataptr() const { + return (_base == MetadataPtr) ? (TypeMetadataPtr*)this : NULL; +} + inline const TypeKlassPtr *Type::isa_klassptr() const { return (_base == KlassPtr) ? (TypeKlassPtr*)this : NULL; } |