src/share/vm/c1/c1_CodeStubs.hpp

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 777
37f87013dfd8
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 class CodeEmitInfo;
    26 class LIR_Assembler;
    27 class LIR_OpVisitState;
    29 // CodeStubs are little 'out-of-line' pieces of code that
    30 // usually handle slow cases of operations. All code stubs
    31 // are collected and code is emitted at the end of the
    32 // nmethod.
    34 class CodeStub: public CompilationResourceObj {
    35  protected:
    36   Label _entry;                                  // label at the stub entry point
    37   Label _continuation;                           // label where stub continues, if any
    39  public:
    40   CodeStub() {}
    42   // code generation
    43   void assert_no_unbound_labels()                { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); }
    44   virtual void emit_code(LIR_Assembler* e) = 0;
    45   virtual CodeEmitInfo* info() const             { return NULL; }
    46   virtual bool is_exception_throw_stub() const   { return false; }
    47   virtual bool is_range_check_stub() const       { return false; }
    48   virtual bool is_divbyzero_stub() const         { return false; }
    49 #ifndef PRODUCT
    50   virtual void print_name(outputStream* out) const = 0;
    51 #endif
    53   // label access
    54   Label* entry()                                 { return &_entry; }
    55   Label* continuation()                          { return &_continuation; }
    56   // for LIR
    57   virtual void visit(LIR_OpVisitState* visit) {
    58 #ifndef PRODUCT
    59     if (LIRTracePeephole && Verbose) {
    60       tty->print("no visitor for ");
    61       print_name(tty);
    62       tty->cr();
    63     }
    64 #endif
    65   }
    66 };
    69 define_array(CodeStubArray, CodeStub*)
    70 define_stack(_CodeStubList, CodeStubArray)
    72 class CodeStubList: public _CodeStubList {
    73  public:
    74   CodeStubList(): _CodeStubList() {}
    76   void append(CodeStub* stub) {
    77     if (!contains(stub)) {
    78       _CodeStubList::append(stub);
    79     }
    80   }
    81 };
    83 #ifdef TIERED
    84 class CounterOverflowStub: public CodeStub {
    85  private:
    86   CodeEmitInfo* _info;
    87   int           _bci;
    89 public:
    90   CounterOverflowStub(CodeEmitInfo* info, int bci) : _info(info), _bci(bci) {
    91   }
    93   virtual void emit_code(LIR_Assembler* e);
    95   virtual void visit(LIR_OpVisitState* visitor) {
    96     visitor->do_slow_case(_info);
    97   }
    99 #ifndef PRODUCT
   100   virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); }
   101 #endif // PRODUCT
   103 };
   104 #endif // TIERED
   106 class ConversionStub: public CodeStub {
   107  private:
   108   Bytecodes::Code _bytecode;
   109   LIR_Opr         _input;
   110   LIR_Opr         _result;
   112   static float float_zero;
   113   static double double_zero;
   114  public:
   115   ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result)
   116     : _bytecode(bytecode), _input(input), _result(result) {
   117   }
   119   Bytecodes::Code bytecode() { return _bytecode; }
   120   LIR_Opr         input()    { return _input; }
   121   LIR_Opr         result()   { return _result; }
   123   virtual void emit_code(LIR_Assembler* e);
   124   virtual void visit(LIR_OpVisitState* visitor) {
   125     visitor->do_slow_case();
   126     visitor->do_input(_input);
   127     visitor->do_output(_result);
   128   }
   129 #ifndef PRODUCT
   130   virtual void print_name(outputStream* out) const { out->print("ConversionStub"); }
   131 #endif // PRODUCT
   132 };
   135 // Throws ArrayIndexOutOfBoundsException by default but can be
   136 // configured to throw IndexOutOfBoundsException in constructor
   137 class RangeCheckStub: public CodeStub {
   138  private:
   139   CodeEmitInfo* _info;
   140   LIR_Opr       _index;
   141   bool          _throw_index_out_of_bounds_exception;
   143  public:
   144   RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false);
   145   virtual void emit_code(LIR_Assembler* e);
   146   virtual CodeEmitInfo* info() const             { return _info; }
   147   virtual bool is_exception_throw_stub() const   { return true; }
   148   virtual bool is_range_check_stub() const       { return true; }
   149   virtual void visit(LIR_OpVisitState* visitor) {
   150     visitor->do_slow_case(_info);
   151     visitor->do_input(_index);
   152   }
   153 #ifndef PRODUCT
   154   virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }
   155 #endif // PRODUCT
   156 };
   159 class DivByZeroStub: public CodeStub {
   160  private:
   161   CodeEmitInfo* _info;
   162   int           _offset;
   164  public:
   165   DivByZeroStub(CodeEmitInfo* info)
   166     : _info(info), _offset(-1) {
   167   }
   168   DivByZeroStub(int offset, CodeEmitInfo* info)
   169     : _info(info), _offset(offset) {
   170   }
   171   virtual void emit_code(LIR_Assembler* e);
   172   virtual CodeEmitInfo* info() const             { return _info; }
   173   virtual bool is_exception_throw_stub() const   { return true; }
   174   virtual bool is_divbyzero_stub() const         { return true; }
   175   virtual void visit(LIR_OpVisitState* visitor) {
   176     visitor->do_slow_case(_info);
   177   }
   178 #ifndef PRODUCT
   179   virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }
   180 #endif // PRODUCT
   181 };
   184 class ImplicitNullCheckStub: public CodeStub {
   185  private:
   186   CodeEmitInfo* _info;
   187   int           _offset;
   189  public:
   190   ImplicitNullCheckStub(int offset, CodeEmitInfo* info)
   191     : _offset(offset), _info(info) {
   192   }
   193   virtual void emit_code(LIR_Assembler* e);
   194   virtual CodeEmitInfo* info() const             { return _info; }
   195   virtual bool is_exception_throw_stub() const   { return true; }
   196   virtual void visit(LIR_OpVisitState* visitor) {
   197     visitor->do_slow_case(_info);
   198   }
   199 #ifndef PRODUCT
   200   virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }
   201 #endif // PRODUCT
   202 };
   205 class NewInstanceStub: public CodeStub {
   206  private:
   207   ciInstanceKlass* _klass;
   208   LIR_Opr          _klass_reg;
   209   LIR_Opr          _result;
   210   CodeEmitInfo*    _info;
   211   Runtime1::StubID _stub_id;
   213  public:
   214   NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id);
   215   virtual void emit_code(LIR_Assembler* e);
   216   virtual CodeEmitInfo* info() const             { return _info; }
   217   virtual void visit(LIR_OpVisitState* visitor) {
   218     visitor->do_slow_case(_info);
   219     visitor->do_input(_klass_reg);
   220     visitor->do_output(_result);
   221   }
   222 #ifndef PRODUCT
   223   virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }
   224 #endif // PRODUCT
   225 };
   228 class NewTypeArrayStub: public CodeStub {
   229  private:
   230   LIR_Opr       _klass_reg;
   231   LIR_Opr       _length;
   232   LIR_Opr       _result;
   233   CodeEmitInfo* _info;
   235  public:
   236   NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
   237   virtual void emit_code(LIR_Assembler* e);
   238   virtual CodeEmitInfo* info() const             { return _info; }
   239   virtual void visit(LIR_OpVisitState* visitor) {
   240     visitor->do_slow_case(_info);
   241     visitor->do_input(_klass_reg);
   242     visitor->do_input(_length);
   243     assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
   244   }
   245 #ifndef PRODUCT
   246   virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }
   247 #endif // PRODUCT
   248 };
   251 class NewObjectArrayStub: public CodeStub {
   252  private:
   253   LIR_Opr        _klass_reg;
   254   LIR_Opr        _length;
   255   LIR_Opr        _result;
   256   CodeEmitInfo*  _info;
   258  public:
   259   NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
   260   virtual void emit_code(LIR_Assembler* e);
   261   virtual CodeEmitInfo* info() const             { return _info; }
   262   virtual void visit(LIR_OpVisitState* visitor) {
   263     visitor->do_slow_case(_info);
   264     visitor->do_input(_klass_reg);
   265     visitor->do_input(_length);
   266     assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
   267   }
   268 #ifndef PRODUCT
   269   virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }
   270 #endif // PRODUCT
   271 };
   274 class MonitorAccessStub: public CodeStub {
   275  protected:
   276   LIR_Opr _obj_reg;
   277   LIR_Opr _lock_reg;
   279  public:
   280   MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {
   281     _obj_reg  = obj_reg;
   282     _lock_reg  = lock_reg;
   283   }
   285 #ifndef PRODUCT
   286   virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }
   287 #endif // PRODUCT
   288 };
   291 class MonitorEnterStub: public MonitorAccessStub {
   292  private:
   293   CodeEmitInfo* _info;
   295  public:
   296   MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info);
   298   virtual void emit_code(LIR_Assembler* e);
   299   virtual CodeEmitInfo* info() const             { return _info; }
   300   virtual void visit(LIR_OpVisitState* visitor) {
   301     visitor->do_input(_obj_reg);
   302     visitor->do_input(_lock_reg);
   303     visitor->do_slow_case(_info);
   304   }
   305 #ifndef PRODUCT
   306   virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }
   307 #endif // PRODUCT
   308 };
   311 class MonitorExitStub: public MonitorAccessStub {
   312  private:
   313   bool _compute_lock;
   314   int  _monitor_ix;
   316  public:
   317   MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix)
   318     : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),
   319       _compute_lock(compute_lock), _monitor_ix(monitor_ix) { }
   320   virtual void emit_code(LIR_Assembler* e);
   321   virtual void visit(LIR_OpVisitState* visitor) {
   322     assert(_obj_reg->is_illegal(), "unused");
   323     if (_compute_lock) {
   324       visitor->do_temp(_lock_reg);
   325     } else {
   326       visitor->do_input(_lock_reg);
   327     }
   328   }
   329 #ifndef PRODUCT
   330   virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }
   331 #endif // PRODUCT
   332 };
   335 class PatchingStub: public CodeStub {
   336  public:
   337   enum PatchID {
   338     access_field_id,
   339     load_klass_id
   340   };
   341   enum constants {
   342     patch_info_size = 3
   343   };
   344  private:
   345   PatchID       _id;
   346   address       _pc_start;
   347   int           _bytes_to_copy;
   348   Label         _patched_code_entry;
   349   Label         _patch_site_entry;
   350   Label         _patch_site_continuation;
   351   Register      _obj;
   352   CodeEmitInfo* _info;
   353   int           _oop_index;  // index of the patchable oop in nmethod oop table if needed
   354   static int    _patch_info_offset;
   356   void align_patch_site(MacroAssembler* masm);
   358  public:
   359   static int patch_info_offset() { return _patch_info_offset; }
   361   PatchingStub(MacroAssembler* masm, PatchID id, int oop_index = -1):
   362       _id(id)
   363     , _info(NULL)
   364     , _oop_index(oop_index) {
   365     if (os::is_MP()) {
   366       // force alignment of patch sites on MP hardware so we
   367       // can guarantee atomic writes to the patch site.
   368       align_patch_site(masm);
   369     }
   370     _pc_start = masm->pc();
   371     masm->bind(_patch_site_entry);
   372   }
   374   void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
   375     _info = info;
   376     _obj = obj;
   377     masm->bind(_patch_site_continuation);
   378     _bytes_to_copy = masm->pc() - pc_start();
   379     if (_id == PatchingStub::access_field_id) {
   380       // embed a fixed offset to handle long patches which need to be offset by a word.
   381       // the patching code will just add the field offset field to this offset so
   382       // that we can refernce either the high or low word of a double word field.
   383       int field_offset = 0;
   384       switch (patch_code) {
   385       case lir_patch_low:         field_offset = lo_word_offset_in_bytes; break;
   386       case lir_patch_high:        field_offset = hi_word_offset_in_bytes; break;
   387       case lir_patch_normal:      field_offset = 0;                       break;
   388       default: ShouldNotReachHere();
   389       }
   390       NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
   391       n_move->set_offset(field_offset);
   392     } else if (_id == load_klass_id) {
   393       assert(_obj != noreg, "must have register object for load_klass");
   394 #ifdef ASSERT
   395       // verify that we're pointing at a NativeMovConstReg
   396       nativeMovConstReg_at(pc_start());
   397 #endif
   398     } else {
   399       ShouldNotReachHere();
   400     }
   401     assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");
   402   }
   404   address pc_start() const                       { return _pc_start; }
   405   PatchID id() const                             { return _id; }
   407   virtual void emit_code(LIR_Assembler* e);
   408   virtual CodeEmitInfo* info() const             { return _info; }
   409   virtual void visit(LIR_OpVisitState* visitor) {
   410     visitor->do_slow_case(_info);
   411   }
   412 #ifndef PRODUCT
   413   virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }
   414 #endif // PRODUCT
   415 };
   418 class SimpleExceptionStub: public CodeStub {
   419  private:
   420   LIR_Opr          _obj;
   421   Runtime1::StubID _stub;
   422   CodeEmitInfo*    _info;
   424  public:
   425   SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info):
   426     _obj(obj), _info(info), _stub(stub) {
   427   }
   429   virtual void emit_code(LIR_Assembler* e);
   430   virtual CodeEmitInfo* info() const             { return _info; }
   431   virtual bool is_exception_throw_stub() const   { return true; }
   432   virtual void visit(LIR_OpVisitState* visitor) {
   433     if (_obj->is_valid()) visitor->do_input(_obj);
   434     visitor->do_slow_case(_info);
   435   }
   436 #ifndef PRODUCT
   437   virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }
   438 #endif // PRODUCT
   439 };
   443 class ArrayStoreExceptionStub: public CodeStub {
   444  private:
   445   CodeEmitInfo* _info;
   447  public:
   448   ArrayStoreExceptionStub(CodeEmitInfo* info);
   449   virtual void emit_code(LIR_Assembler* emit);
   450   virtual CodeEmitInfo* info() const             { return _info; }
   451   virtual bool is_exception_throw_stub() const   { return true; }
   452   virtual void visit(LIR_OpVisitState* visitor) {
   453     visitor->do_slow_case(_info);
   454   }
   455 #ifndef PRODUCT
   456   virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
   457 #endif // PRODUCT
   458 };
   461 class ArrayCopyStub: public CodeStub {
   462  private:
   463   LIR_OpArrayCopy* _op;
   465  public:
   466   ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { }
   468   LIR_Opr src() const                         { return _op->src(); }
   469   LIR_Opr src_pos() const                     { return _op->src_pos(); }
   470   LIR_Opr dst() const                         { return _op->dst(); }
   471   LIR_Opr dst_pos() const                     { return _op->dst_pos(); }
   472   LIR_Opr length() const                      { return _op->length(); }
   473   LIR_Opr tmp() const                         { return _op->tmp(); }
   475   virtual void emit_code(LIR_Assembler* e);
   476   virtual CodeEmitInfo* info() const          { return _op->info(); }
   477   virtual void visit(LIR_OpVisitState* visitor) {
   478     // don't pass in the code emit info since it's processed in the fast path
   479     visitor->do_slow_case();
   480   }
   481 #ifndef PRODUCT
   482   virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }
   483 #endif // PRODUCT
   484 };

mercurial