1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/c1/c1_IR.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,376 @@ 1.4 +/* 1.5 + * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// An XHandler is a C1 internal description for an exception handler 1.29 + 1.30 +class XHandler: public CompilationResourceObj { 1.31 + private: 1.32 + ciExceptionHandler* _desc; 1.33 + 1.34 + BlockBegin* _entry_block; // Entry block of xhandler 1.35 + LIR_List* _entry_code; // LIR-operations that must be executed before jumping to entry_block 1.36 + int _entry_pco; // pco where entry_code (or entry_block if no entry_code) starts 1.37 + int _phi_operand; // For resolving of phi functions at begin of entry_block 1.38 + int _scope_count; // for filling ExceptionRangeEntry::scope_count 1.39 + 1.40 +#ifdef ASSERT 1.41 + int _lir_op_id; // op_id of the LIR-operation throwing to this handler 1.42 +#endif 1.43 + 1.44 + public: 1.45 + // creation 1.46 + XHandler(ciExceptionHandler* desc) 1.47 + : _desc(desc) 1.48 + , _entry_block(NULL) 1.49 + , _entry_code(NULL) 1.50 + , _entry_pco(-1) 1.51 + , _phi_operand(-1) 1.52 + , _scope_count(-1) 1.53 +#ifdef ASSERT 1.54 + , _lir_op_id(-1) 1.55 +#endif 1.56 + { } 1.57 + 1.58 + XHandler(XHandler* other) 1.59 + : _desc(other->_desc) 1.60 + , _entry_block(other->_entry_block) 1.61 + , _entry_code(other->_entry_code) 1.62 + , _entry_pco(other->_entry_pco) 1.63 + , _phi_operand(other->_phi_operand) 1.64 + , _scope_count(other->_scope_count) 1.65 +#ifdef ASSERT 1.66 + , _lir_op_id(other->_lir_op_id) 1.67 +#endif 1.68 + { } 1.69 + 1.70 + // accessors for data of ciExceptionHandler 1.71 + int beg_bci() const { return _desc->start(); } 1.72 + int end_bci() const { return _desc->limit(); } 1.73 + int handler_bci() const { return _desc->handler_bci(); } 1.74 + bool is_catch_all() const { return _desc->is_catch_all(); } 1.75 + int catch_type() const { return _desc->catch_klass_index(); } 1.76 + ciInstanceKlass* catch_klass() const { return _desc->catch_klass(); } 1.77 + bool covers(int bci) const { return beg_bci() <= bci && bci < end_bci(); } 1.78 + 1.79 + // accessors for additional fields 1.80 + BlockBegin* entry_block() const { return _entry_block; } 1.81 + LIR_List* entry_code() const { return _entry_code; } 1.82 + int entry_pco() const { return _entry_pco; } 1.83 + int phi_operand() const { assert(_phi_operand != -1, "not set"); return _phi_operand; } 1.84 + int scope_count() const { assert(_scope_count != -1, "not set"); return _scope_count; } 1.85 + DEBUG_ONLY(int lir_op_id() const { return _lir_op_id; }); 1.86 + 1.87 + void set_entry_block(BlockBegin* entry_block) { 1.88 + assert(entry_block->is_set(BlockBegin::exception_entry_flag), "must be an exception handler entry"); 1.89 + assert(entry_block->bci() == handler_bci(), "bci's must correspond"); 1.90 + _entry_block = entry_block; 1.91 + } 1.92 + void set_entry_code(LIR_List* entry_code) { _entry_code = entry_code; } 1.93 + void set_entry_pco(int entry_pco) { _entry_pco = entry_pco; } 1.94 + void set_phi_operand(int phi_operand) { _phi_operand = phi_operand; } 1.95 + void set_scope_count(int scope_count) { _scope_count = scope_count; } 1.96 + DEBUG_ONLY(void set_lir_op_id(int lir_op_id) { _lir_op_id = lir_op_id; }); 1.97 + 1.98 + bool equals(XHandler* other) const; 1.99 +}; 1.100 + 1.101 +define_array(_XHandlerArray, XHandler*) 1.102 +define_stack(_XHandlerList, _XHandlerArray) 1.103 + 1.104 + 1.105 +// XHandlers is the C1 internal list of exception handlers for a method 1.106 +class XHandlers: public CompilationResourceObj { 1.107 + private: 1.108 + _XHandlerList _list; 1.109 + 1.110 + public: 1.111 + // creation 1.112 + XHandlers() : _list() { } 1.113 + XHandlers(ciMethod* method); 1.114 + XHandlers(XHandlers* other); 1.115 + 1.116 + // accessors 1.117 + int length() const { return _list.length(); } 1.118 + XHandler* handler_at(int i) const { return _list.at(i); } 1.119 + bool has_handlers() const { return _list.length() > 0; } 1.120 + void append(XHandler* h) { _list.append(h); } 1.121 + XHandler* remove_last() { return _list.pop(); } 1.122 + 1.123 + bool could_catch(ciInstanceKlass* klass, bool type_is_exact) const; 1.124 + bool equals(XHandlers* others) const; 1.125 +}; 1.126 + 1.127 + 1.128 +class IRScope; 1.129 +define_array(IRScopeArray, IRScope*) 1.130 +define_stack(IRScopeList, IRScopeArray) 1.131 + 1.132 +class Compilation; 1.133 +class IRScope: public CompilationResourceObj { 1.134 + private: 1.135 + // hierarchy 1.136 + Compilation* _compilation; // the current compilation 1.137 + IRScope* _caller; // the caller scope, or NULL 1.138 + int _caller_bci; // the caller bci of the corresponding (inlined) invoke, or < 0 1.139 + ValueStack* _caller_state; // the caller state, or NULL 1.140 + int _level; // the inlining level 1.141 + ciMethod* _method; // the corresponding method 1.142 + IRScopeList _callees; // the inlined method scopes 1.143 + 1.144 + // graph 1.145 + XHandlers* _xhandlers; // the exception handlers 1.146 + int _number_of_locks; // the number of monitor lock slots needed 1.147 + bool _monitor_pairing_ok; // the monitor pairing info 1.148 + BlockBegin* _start; // the start block, successsors are method entries 1.149 + 1.150 + // lock stack management 1.151 + int _lock_stack_size; // number of expression stack elements which, if present, 1.152 + // must be spilled to the stack because of exception 1.153 + // handling inside inlined methods 1.154 + 1.155 + BitMap _requires_phi_function; // bit is set if phi functions at loop headers are necessary for a local variable 1.156 + 1.157 + // helper functions 1.158 + BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state); 1.159 + BlockBegin* build_graph(Compilation* compilation, int osr_bci); 1.160 + 1.161 + public: 1.162 + // creation 1.163 + IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph = false); 1.164 + 1.165 + // accessors 1.166 + Compilation* compilation() const { return _compilation; } 1.167 + IRScope* caller() const { return _caller; } 1.168 + int caller_bci() const { return _caller_bci; } 1.169 + ValueStack* caller_state() const { return _caller_state; } 1.170 + int level() const { return _level; } 1.171 + ciMethod* method() const { return _method; } 1.172 + int max_stack() const; // NOTE: expensive 1.173 + int lock_stack_size() const { 1.174 + assert(_lock_stack_size != -1, "uninitialized"); 1.175 + return _lock_stack_size; 1.176 + } 1.177 + BitMap& requires_phi_function() { return _requires_phi_function; } 1.178 + 1.179 + // mutators 1.180 + // Needed because caller state is not ready at time of IRScope construction 1.181 + void set_caller_state(ValueStack* state) { _caller_state = state; } 1.182 + // Needed because caller state changes after IRScope construction. 1.183 + // Computes number of expression stack elements whose state must be 1.184 + // preserved in the case of an exception; these may be seen by 1.185 + // caller scopes. Zero when inlining of methods containing exception 1.186 + // handlers is disabled, otherwise a conservative approximation. 1.187 + void compute_lock_stack_size(); 1.188 + 1.189 + // hierarchy 1.190 + bool is_top_scope() const { return _caller == NULL; } 1.191 + void add_callee(IRScope* callee) { _callees.append(callee); } 1.192 + int number_of_callees() const { return _callees.length(); } 1.193 + IRScope* callee_no(int i) const { return _callees.at(i); } 1.194 + int top_scope_bci() const; 1.195 + 1.196 + // accessors, graph 1.197 + bool is_valid() const { return start() != NULL; } 1.198 + XHandlers* xhandlers() const { return _xhandlers; } 1.199 + int number_of_locks() const { return _number_of_locks; } 1.200 + void set_min_number_of_locks(int n) { if (n > _number_of_locks) _number_of_locks = n; } 1.201 + bool monitor_pairing_ok() const { return _monitor_pairing_ok; } 1.202 + BlockBegin* start() const { return _start; } 1.203 +}; 1.204 + 1.205 + 1.206 +// 1.207 +// IRScopeDebugInfo records the debug information for a particular IRScope 1.208 +// in a particular CodeEmitInfo. This allows the information to be computed 1.209 +// once early enough for the OopMap to be available to the LIR and also to be 1.210 +// reemited for different pcs using the same CodeEmitInfo without recomputing 1.211 +// everything. 1.212 +// 1.213 + 1.214 +class IRScopeDebugInfo: public CompilationResourceObj { 1.215 + private: 1.216 + IRScope* _scope; 1.217 + int _bci; 1.218 + GrowableArray<ScopeValue*>* _locals; 1.219 + GrowableArray<ScopeValue*>* _expressions; 1.220 + GrowableArray<MonitorValue*>* _monitors; 1.221 + IRScopeDebugInfo* _caller; 1.222 + 1.223 + public: 1.224 + IRScopeDebugInfo(IRScope* scope, 1.225 + int bci, 1.226 + GrowableArray<ScopeValue*>* locals, 1.227 + GrowableArray<ScopeValue*>* expressions, 1.228 + GrowableArray<MonitorValue*>* monitors, 1.229 + IRScopeDebugInfo* caller): 1.230 + _scope(scope) 1.231 + , _locals(locals) 1.232 + , _bci(bci) 1.233 + , _expressions(expressions) 1.234 + , _monitors(monitors) 1.235 + , _caller(caller) {} 1.236 + 1.237 + 1.238 + IRScope* scope() { return _scope; } 1.239 + int bci() { return _bci; } 1.240 + GrowableArray<ScopeValue*>* locals() { return _locals; } 1.241 + GrowableArray<ScopeValue*>* expressions() { return _expressions; } 1.242 + GrowableArray<MonitorValue*>* monitors() { return _monitors; } 1.243 + IRScopeDebugInfo* caller() { return _caller; } 1.244 + 1.245 + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { 1.246 + if (caller() != NULL) { 1.247 + // Order is significant: Must record caller first. 1.248 + caller()->record_debug_info(recorder, pc_offset); 1.249 + } 1.250 + DebugToken* locvals = recorder->create_scope_values(locals()); 1.251 + DebugToken* expvals = recorder->create_scope_values(expressions()); 1.252 + DebugToken* monvals = recorder->create_monitor_values(monitors()); 1.253 + recorder->describe_scope(pc_offset, scope()->method(), bci(), locvals, expvals, monvals); 1.254 + } 1.255 +}; 1.256 + 1.257 + 1.258 +class CodeEmitInfo: public CompilationResourceObj { 1.259 + friend class LinearScan; 1.260 + private: 1.261 + IRScopeDebugInfo* _scope_debug_info; 1.262 + IRScope* _scope; 1.263 + XHandlers* _exception_handlers; 1.264 + OopMap* _oop_map; 1.265 + ValueStack* _stack; // used by deoptimization (contains also monitors 1.266 + int _bci; 1.267 + CodeEmitInfo* _next; 1.268 + int _id; 1.269 + 1.270 + FrameMap* frame_map() const { return scope()->compilation()->frame_map(); } 1.271 + Compilation* compilation() const { return scope()->compilation(); } 1.272 + 1.273 + public: 1.274 + 1.275 + // use scope from ValueStack 1.276 + CodeEmitInfo(int bci, ValueStack* stack, XHandlers* exception_handlers); 1.277 + 1.278 + // used by natives 1.279 + CodeEmitInfo(IRScope* scope, int bci) 1.280 + : _scope(scope) 1.281 + , _bci(bci) 1.282 + , _oop_map(NULL) 1.283 + , _scope_debug_info(NULL) 1.284 + , _stack(NULL) 1.285 + , _exception_handlers(NULL) 1.286 + , _next(NULL) 1.287 + , _id(-1) { 1.288 + } 1.289 + 1.290 + // make a copy 1.291 + CodeEmitInfo(CodeEmitInfo* info, bool lock_stack_only = false); 1.292 + 1.293 + // accessors 1.294 + OopMap* oop_map() { return _oop_map; } 1.295 + ciMethod* method() const { return _scope->method(); } 1.296 + IRScope* scope() const { return _scope; } 1.297 + XHandlers* exception_handlers() const { return _exception_handlers; } 1.298 + ValueStack* stack() const { return _stack; } 1.299 + int bci() const { return _bci; } 1.300 + 1.301 + void add_register_oop(LIR_Opr opr); 1.302 + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset); 1.303 + 1.304 + CodeEmitInfo* next() const { return _next; } 1.305 + void set_next(CodeEmitInfo* next) { _next = next; } 1.306 + 1.307 + int id() const { return _id; } 1.308 + void set_id(int id) { _id = id; } 1.309 +}; 1.310 + 1.311 + 1.312 +class IR: public CompilationResourceObj { 1.313 + private: 1.314 + Compilation* _compilation; // the current compilation 1.315 + IRScope* _top_scope; // the root of the scope hierarchy 1.316 + WordSize _locals_size; // the space required for all locals 1.317 + int _num_loops; // Total number of loops 1.318 + BlockList* _code; // the blocks in code generation order w/ use counts 1.319 + 1.320 + public: 1.321 + // creation 1.322 + IR(Compilation* compilation, ciMethod* method, int osr_bci); 1.323 + 1.324 + // accessors 1.325 + bool is_valid() const { return top_scope()->is_valid(); } 1.326 + Compilation* compilation() const { return _compilation; } 1.327 + IRScope* top_scope() const { return _top_scope; } 1.328 + int number_of_locks() const { return top_scope()->number_of_locks(); } 1.329 + ciMethod* method() const { return top_scope()->method(); } 1.330 + BlockBegin* start() const { return top_scope()->start(); } 1.331 + BlockBegin* std_entry() const { return start()->end()->as_Base()->std_entry(); } 1.332 + BlockBegin* osr_entry() const { return start()->end()->as_Base()->osr_entry(); } 1.333 + WordSize locals_size() const { return _locals_size; } 1.334 + int locals_size_in_words() const { return in_words(_locals_size); } 1.335 + BlockList* code() const { return _code; } 1.336 + int num_loops() const { return _num_loops; } 1.337 + int max_stack() const { return top_scope()->max_stack(); } // expensive 1.338 + 1.339 + // ir manipulation 1.340 + void optimize(); 1.341 + void compute_predecessors(); 1.342 + void split_critical_edges(); 1.343 + void compute_code(); 1.344 + void compute_use_counts(); 1.345 + 1.346 + // The linear-scan order and the code emission order are equal, but 1.347 + // this may change in future 1.348 + BlockList* linear_scan_order() { assert(_code != NULL, "not computed"); return _code; } 1.349 + 1.350 + // iteration 1.351 + void iterate_preorder (BlockClosure* closure); 1.352 + void iterate_postorder (BlockClosure* closure); 1.353 + void iterate_linear_scan_order(BlockClosure* closure); 1.354 + 1.355 + // debugging 1.356 + static void print(BlockBegin* start, bool cfg_only, bool live_only = false) PRODUCT_RETURN; 1.357 + void print(bool cfg_only, bool live_only = false) PRODUCT_RETURN; 1.358 + void verify() PRODUCT_RETURN; 1.359 +}; 1.360 + 1.361 + 1.362 +// Globally do instruction substitution and remove substituted 1.363 +// instructions from the instruction list. 1.364 +// 1.365 + 1.366 +class SubstitutionResolver: public BlockClosure { 1.367 + static void substitute(Value* v); 1.368 + 1.369 + public: 1.370 + SubstitutionResolver(IR* hir) { 1.371 + hir->iterate_preorder(this); 1.372 + } 1.373 + 1.374 + SubstitutionResolver(BlockBegin* block) { 1.375 + block->iterate_preorder(this); 1.376 + } 1.377 + 1.378 + virtual void block_do(BlockBegin* block); 1.379 +};