src/cpu/ppc/vm/nativeInst_ppc.hpp

Wed, 27 Nov 2013 16:16:21 -0800

author
goetz
date
Wed, 27 Nov 2013 16:16:21 -0800
changeset 6490
41b780b43b74
parent 6458
ec28f9c041ff
child 6495
67fa91961822
permissions
-rw-r--r--

8029015: PPC64 (part 216): opto: trap based null and range checks
Summary: On PPC64 use tdi instruction that does a compare and raises SIGTRAP for NULL and range checks.
Reviewed-by: kvn

     1 /*
     2  * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright 2012, 2013 SAP AG. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  *
    24  */
    26 #ifndef CPU_PPC_VM_NATIVEINST_PPC_HPP
    27 #define CPU_PPC_VM_NATIVEINST_PPC_HPP
    29 #include "asm/assembler.hpp"
    30 #include "asm/macroAssembler.hpp"
    31 #include "memory/allocation.hpp"
    32 #include "runtime/icache.hpp"
    33 #include "runtime/os.hpp"
    34 #include "utilities/top.hpp"
    36 // We have interfaces for the following instructions:
    37 //
    38 // - NativeInstruction
    39 //   - NativeCall
    40 //   - NativeFarCall
    41 //   - NativeMovConstReg
    42 //   - NativeJump
    43 //   - NativeIllegalInstruction
    44 //   - NativeConditionalFarBranch
    45 //   - NativeCallTrampolineStub
    47 // The base class for different kinds of native instruction abstractions.
    48 // It provides the primitive operations to manipulate code relative to this.
    49 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
    50   friend class Relocation;
    52  public:
    53   bool is_sigtrap_ic_miss_check() {
    54     assert(UseSIGTRAP, "precondition");
    55     return MacroAssembler::is_trap_ic_miss_check(long_at(0));
    56   }
    58   bool is_sigtrap_null_check() {
    59     assert(UseSIGTRAP && TrapBasedNullChecks, "precondition");
    60     return MacroAssembler::is_trap_null_check(long_at(0));
    61   }
    63   // We use a special trap for marking a method as not_entrant or zombie
    64   // iff UseSIGTRAP.
    65   bool is_sigtrap_zombie_not_entrant() {
    66     assert(UseSIGTRAP, "precondition");
    67     return MacroAssembler::is_trap_zombie_not_entrant(long_at(0));
    68   }
    70   // We use an illtrap for marking a method as not_entrant or zombie
    71   // iff !UseSIGTRAP.
    72   bool is_sigill_zombie_not_entrant() {
    73     assert(!UseSIGTRAP, "precondition");
    74     // Work around a C++ compiler bug which changes 'this'.
    75     return NativeInstruction::is_sigill_zombie_not_entrant_at(addr_at(0));
    76   }
    77   static bool is_sigill_zombie_not_entrant_at(address addr);
    79 #ifdef COMPILER2
    80   // SIGTRAP-based implicit range checks
    81   bool is_sigtrap_range_check() {
    82     assert(UseSIGTRAP && TrapBasedRangeChecks, "precondition");
    83     return MacroAssembler::is_trap_range_check(long_at(0));
    84   }
    85 #endif
    87   // 'should not reach here'.
    88   bool is_sigtrap_should_not_reach_here() {
    89     return MacroAssembler::is_trap_should_not_reach_here(long_at(0));
    90   }
    92   bool is_safepoint_poll() {
    93     // Is the current instruction a POTENTIAL read access to the polling page?
    94     // The current arguments of the instruction are not checked!
    95     return MacroAssembler::is_load_from_polling_page(long_at(0), NULL);
    96   }
    98   bool is_memory_serialization(JavaThread *thread, void *ucontext) {
    99     // Is the current instruction a write access of thread to the
   100     // memory serialization page?
   101     return MacroAssembler::is_memory_serialization(long_at(0), thread, ucontext);
   102   }
   104   address get_stack_bang_address(void *ucontext) {
   105     // If long_at(0) is not a stack bang, return 0. Otherwise, return
   106     // banged address.
   107     return MacroAssembler::get_stack_bang_address(long_at(0), ucontext);
   108   }
   110  protected:
   111   address  addr_at(int offset) const    { return address(this) + offset; }
   112   int      long_at(int offset) const    { return *(int*)addr_at(offset); }
   114  public:
   115   void verify() NOT_DEBUG_RETURN;
   116 };
   118 inline NativeInstruction* nativeInstruction_at(address address) {
   119   NativeInstruction* inst = (NativeInstruction*)address;
   120   inst->verify();
   121   return inst;
   122 }
   124 // The NativeCall is an abstraction for accessing/manipulating call
   125 // instructions. It is used to manipulate inline caches, primitive &
   126 // dll calls, etc.
   127 //
   128 // Sparc distinguishes `NativeCall' and `NativeFarCall'. On PPC64,
   129 // at present, we provide a single class `NativeCall' representing the
   130 // sequence `load_const, mtctr, bctrl' or the sequence 'ld_from_toc,
   131 // mtctr, bctrl'.
   132 class NativeCall: public NativeInstruction {
   133  public:
   135   enum specific_constants {
   136     load_const_instruction_size                 = 28,
   137     load_const_from_method_toc_instruction_size = 16,
   138     instruction_size                            = 16 // Used in shared code for calls with reloc_info.
   139   };
   141   static bool is_call_at(address a) {
   142     return Assembler::is_bl(*(int*)(a));
   143   }
   145   static bool is_call_before(address return_address) {
   146     return NativeCall::is_call_at(return_address - 4);
   147   }
   149   address instruction_address() const {
   150     return addr_at(0);
   151   }
   153   address next_instruction_address() const {
   154     // We have only bl.
   155     assert(MacroAssembler::is_bl(*(int*)instruction_address()), "Should be bl instruction!");
   156     return addr_at(4);
   157   }
   159   address return_address() const {
   160     return next_instruction_address();
   161   }
   163   address destination() const;
   165   // The parameter assert_lock disables the assertion during code generation.
   166   void set_destination_mt_safe(address dest, bool assert_lock = true);
   168   address get_trampoline();
   170   void verify_alignment() {} // do nothing on ppc
   171   void verify() NOT_DEBUG_RETURN;
   172 };
   174 inline NativeCall* nativeCall_at(address instr) {
   175   NativeCall* call = (NativeCall*)instr;
   176   call->verify();
   177   return call;
   178 }
   180 inline NativeCall* nativeCall_before(address return_address) {
   181   NativeCall* call = NULL;
   182   if (MacroAssembler::is_bl(*(int*)(return_address - 4)))
   183     call = (NativeCall*)(return_address - 4);
   184   call->verify();
   185   return call;
   186 }
   188 // The NativeFarCall is an abstraction for accessing/manipulating native
   189 // call-anywhere instructions.
   190 // Used to call native methods which may be loaded anywhere in the address
   191 // space, possibly out of reach of a call instruction.
   192 class NativeFarCall: public NativeInstruction {
   193  public:
   194   // We use MacroAssembler::bl64_patchable() for implementing a
   195   // call-anywhere instruction.
   197   // Checks whether instr points at a NativeFarCall instruction.
   198   static bool is_far_call_at(address instr) {
   199     return MacroAssembler::is_bl64_patchable_at(instr);
   200   }
   202   // Does the NativeFarCall implementation use a pc-relative encoding
   203   // of the call destination?
   204   // Used when relocating code.
   205   bool is_pcrelative() {
   206     assert(MacroAssembler::is_bl64_patchable_at((address)this),
   207            "unexpected call type");
   208     return MacroAssembler::is_bl64_patchable_pcrelative_at((address)this);
   209   }
   211   // Returns the NativeFarCall's destination.
   212   address destination() const {
   213     assert(MacroAssembler::is_bl64_patchable_at((address)this),
   214            "unexpected call type");
   215     return MacroAssembler::get_dest_of_bl64_patchable_at((address)this);
   216   }
   218   // Sets the NativeCall's destination, not necessarily mt-safe.
   219   // Used when relocating code.
   220   void set_destination(address dest) {
   221     // Set new destination (implementation of call may change here).
   222     assert(MacroAssembler::is_bl64_patchable_at((address)this),
   223            "unexpected call type");
   224     MacroAssembler::set_dest_of_bl64_patchable_at((address)this, dest);
   225   }
   227   void verify() NOT_DEBUG_RETURN;
   228 };
   230 // Instantiates a NativeFarCall object starting at the given instruction
   231 // address and returns the NativeFarCall object.
   232 inline NativeFarCall* nativeFarCall_at(address instr) {
   233   NativeFarCall* call = (NativeFarCall*)instr;
   234   call->verify();
   235   return call;
   236 }
   238 // An interface for accessing/manipulating native set_oop imm, reg instructions.
   239 // (used to manipulate inlined data references, etc.)
   240 class NativeMovConstReg: public NativeInstruction {
   241  public:
   243   enum specific_constants {
   244     load_const_instruction_size                 = 20,
   245     load_const_from_method_toc_instruction_size =  8,
   246     instruction_size                            =  8 // Used in shared code for calls with reloc_info.
   247   };
   249   address instruction_address() const {
   250     return addr_at(0);
   251   }
   253   address next_instruction_address() const;
   255   // (The [set_]data accessor respects oop_type relocs also.)
   256   intptr_t data() const;
   258   // Patch the code stream.
   259   address set_data_plain(intptr_t x, CodeBlob *code);
   260   // Patch the code stream and oop pool.
   261   void set_data(intptr_t x);
   263   // Patch narrow oop constants. Use this also for narrow klass.
   264   void set_narrow_oop(narrowOop data, CodeBlob *code = NULL);
   266   void verify() NOT_DEBUG_RETURN;
   267 };
   269 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
   270   NativeMovConstReg* test = (NativeMovConstReg*)address;
   271   test->verify();
   272   return test;
   273 }
   275 // The NativeJump is an abstraction for accessing/manipulating native
   276 // jump-anywhere instructions.
   277 class NativeJump: public NativeInstruction {
   278  public:
   279   // We use MacroAssembler::b64_patchable() for implementing a
   280   // jump-anywhere instruction.
   282   enum specific_constants {
   283     instruction_size = MacroAssembler::b64_patchable_size
   284   };
   286   // Checks whether instr points at a NativeJump instruction.
   287   static bool is_jump_at(address instr) {
   288     return MacroAssembler::is_b64_patchable_at(instr)
   289       || (   MacroAssembler::is_load_const_from_method_toc_at(instr)
   290           && Assembler::is_mtctr(*(int*)(instr + 2 * 4))
   291           && Assembler::is_bctr(*(int*)(instr + 3 * 4)));
   292   }
   294   // Does the NativeJump implementation use a pc-relative encoding
   295   // of the call destination?
   296   // Used when relocating code or patching jumps.
   297   bool is_pcrelative() {
   298     return MacroAssembler::is_b64_patchable_pcrelative_at((address)this);
   299   }
   301   // Returns the NativeJump's destination.
   302   address jump_destination() const {
   303     if (MacroAssembler::is_b64_patchable_at((address)this)) {
   304       return MacroAssembler::get_dest_of_b64_patchable_at((address)this);
   305     } else if (MacroAssembler::is_load_const_from_method_toc_at((address)this)
   306                && Assembler::is_mtctr(*(int*)((address)this + 2 * 4))
   307                && Assembler::is_bctr(*(int*)((address)this + 3 * 4))) {
   308       return (address)((NativeMovConstReg *)this)->data();
   309     } else {
   310       ShouldNotReachHere();
   311       return NULL;
   312     }
   313   }
   315   // Sets the NativeJump's destination, not necessarily mt-safe.
   316   // Used when relocating code or patching jumps.
   317   void set_jump_destination(address dest) {
   318     // Set new destination (implementation of call may change here).
   319     if (MacroAssembler::is_b64_patchable_at((address)this)) {
   320       MacroAssembler::set_dest_of_b64_patchable_at((address)this, dest);
   321     } else if (MacroAssembler::is_load_const_from_method_toc_at((address)this)
   322                && Assembler::is_mtctr(*(int*)((address)this + 2 * 4))
   323                && Assembler::is_bctr(*(int*)((address)this + 3 * 4))) {
   324       ((NativeMovConstReg *)this)->set_data((intptr_t)dest);
   325     } else {
   326       ShouldNotReachHere();
   327     }
   328   }
   330   // MT-safe insertion of native jump at verified method entry
   331   static void patch_verified_entry(address entry, address verified_entry, address dest);
   333   void verify() NOT_DEBUG_RETURN;
   335   static void check_verified_entry_alignment(address entry, address verified_entry) {
   336     // We just patch one instruction on ppc64, so the jump doesn't have to
   337     // be aligned. Nothing to do here.
   338   }
   339 };
   341 // Instantiates a NativeJump object starting at the given instruction
   342 // address and returns the NativeJump object.
   343 inline NativeJump* nativeJump_at(address instr) {
   344   NativeJump* call = (NativeJump*)instr;
   345   call->verify();
   346   return call;
   347 }
   349 // NativeConditionalFarBranch is abstraction for accessing/manipulating
   350 // conditional far branches.
   351 class NativeConditionalFarBranch : public NativeInstruction {
   352  public:
   354   static bool is_conditional_far_branch_at(address instr) {
   355     return MacroAssembler::is_bc_far_at(instr);
   356   }
   358   address branch_destination() const {
   359     return MacroAssembler::get_dest_of_bc_far_at((address)this);
   360   }
   362   void set_branch_destination(address dest) {
   363     MacroAssembler::set_dest_of_bc_far_at((address)this, dest);
   364   }
   365 };
   367 inline NativeConditionalFarBranch* NativeConditionalFarBranch_at(address address) {
   368   assert(NativeConditionalFarBranch::is_conditional_far_branch_at(address),
   369          "must be a conditional far branch");
   370   return (NativeConditionalFarBranch*)address;
   371 }
   373 // Call trampoline stubs.
   374 class NativeCallTrampolineStub : public NativeInstruction {
   375  private:
   377   address encoded_destination_addr() const;
   379  public:
   381   address destination() const;
   382   int destination_toc_offset() const;
   384   void set_destination(address new_destination);
   385 };
   388 inline bool is_NativeCallTrampolineStub_at(address address) {
   389   int first_instr = *(int*)address;
   390   return Assembler::is_addis(first_instr) &&
   391     (Register)(intptr_t)Assembler::inv_rt_field(first_instr) == R12_scratch2;
   392 }
   394 inline NativeCallTrampolineStub* NativeCallTrampolineStub_at(address address) {
   395   assert(is_NativeCallTrampolineStub_at(address), "no call trampoline found");
   396   return (NativeCallTrampolineStub*)address;
   397 }
   399 #endif // CPU_PPC_VM_NATIVEINST_PPC_HPP

mercurial