6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes

Thu, 17 Apr 2008 22:18:15 -0400

author
kamg
date
Thu, 17 Apr 2008 22:18:15 -0400
changeset 551
018d5b58dd4f
parent 550
e7a91a357527
child 556
86a689f680c5

6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
Summary: Initial checkin of JSDT code
Reviewed-by: acorn, sbohne

make/linux/makefiles/mapfile-vers-debug file | annotate | diff | comparison | revisions
make/linux/makefiles/mapfile-vers-product file | annotate | diff | comparison | revisions
make/solaris/makefiles/dtrace.make file | annotate | diff | comparison | revisions
make/solaris/makefiles/mapfile-vers file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/nativeInst_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/nativeInst_sparc.hpp file | annotate | diff | comparison | revisions
src/cpu/sparc/vm/sharedRuntime_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/nativeInst_x86.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/nativeInst_x86.hpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/sharedRuntime_x86_32.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/sharedRuntime_x86_64.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/dtraceJSDT_linux.cpp file | annotate | diff | comparison | revisions
src/os/solaris/vm/dtraceJSDT_solaris.cpp file | annotate | diff | comparison | revisions
src/os/windows/vm/dtraceJSDT_windows.cpp file | annotate | diff | comparison | revisions
src/share/vm/asm/codeBuffer.hpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.cpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.hpp file | annotate | diff | comparison | revisions
src/share/vm/includeDB_core file | annotate | diff | comparison | revisions
src/share/vm/oops/methodOop.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvm.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvm.h file | annotate | diff | comparison | revisions
src/share/vm/runtime/dtraceJSDT.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/dtraceJSDT.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/make/linux/makefiles/mapfile-vers-debug	Wed Apr 16 17:36:29 2008 -0400
     1.2 +++ b/make/linux/makefiles/mapfile-vers-debug	Thu Apr 17 22:18:15 2008 -0400
     1.3 @@ -1,3 +1,5 @@
     1.4 +#
     1.5 +# @(#)mapfile-vers-debug	1.18 07/10/25 16:47:35
     1.6  #
     1.7  
     1.8  #
     1.9 @@ -75,6 +77,11 @@
    1.10                  JVM_DesiredAssertionStatus;
    1.11                  JVM_DisableCompiler;
    1.12                  JVM_DoPrivileged;
    1.13 +                JVM_DTraceGetVersion;
    1.14 +                JVM_DTraceActivate;
    1.15 +                JVM_DTraceIsProbeEnabled;
    1.16 +                JVM_DTraceIsSupported;
    1.17 +                JVM_DTraceDispose;
    1.18                  JVM_DumpAllStacks;
    1.19                  JVM_DumpThreads;
    1.20                  JVM_EnableCompiler;
     2.1 --- a/make/linux/makefiles/mapfile-vers-product	Wed Apr 16 17:36:29 2008 -0400
     2.2 +++ b/make/linux/makefiles/mapfile-vers-product	Thu Apr 17 22:18:15 2008 -0400
     2.3 @@ -1,3 +1,5 @@
     2.4 +#
     2.5 +# @(#)mapfile-vers-product	1.19 08/02/12 10:56:37
     2.6  #
     2.7  
     2.8  #
     2.9 @@ -75,6 +77,11 @@
    2.10                  JVM_DesiredAssertionStatus;
    2.11                  JVM_DisableCompiler;
    2.12                  JVM_DoPrivileged;
    2.13 +                JVM_DTraceGetVersion;
    2.14 +                JVM_DTraceActivate;
    2.15 +                JVM_DTraceIsProbeEnabled;
    2.16 +                JVM_DTraceIsSupported;
    2.17 +                JVM_DTraceDispose;
    2.18                  JVM_DumpAllStacks;
    2.19                  JVM_DumpThreads;
    2.20                  JVM_EnableCompiler;
     3.1 --- a/make/solaris/makefiles/dtrace.make	Wed Apr 16 17:36:29 2008 -0400
     3.2 +++ b/make/solaris/makefiles/dtrace.make	Thu Apr 17 22:18:15 2008 -0400
     3.3 @@ -193,10 +193,16 @@
     3.4  
     3.5  .PHONY: dtraceCheck
     3.6  
     3.7 +SYSTEM_DTRACE_H = /usr/include/dtrace.h
     3.8  SYSTEM_DTRACE_PROG = /usr/sbin/dtrace
     3.9  PATCH_DTRACE_PROG = /opt/SUNWdtrd/sbin/dtrace
    3.10  systemDtraceFound := $(wildcard ${SYSTEM_DTRACE_PROG})
    3.11  patchDtraceFound := $(wildcard ${PATCH_DTRACE_PROG})
    3.12 +systemDtraceHdrFound := $(wildcard $(SYSTEM_DTRACE_H))
    3.13 +
    3.14 +ifneq ("$(systemDtraceHdrFound)", "") 
    3.15 +CFLAGS += -DHAVE_DTRACE_H
    3.16 +endif
    3.17  
    3.18  ifneq ("$(patchDtraceFound)", "")
    3.19  DTRACE_PROG=$(PATCH_DTRACE_PROG)
     4.1 --- a/make/solaris/makefiles/mapfile-vers	Wed Apr 16 17:36:29 2008 -0400
     4.2 +++ b/make/solaris/makefiles/mapfile-vers	Thu Apr 17 22:18:15 2008 -0400
     4.3 @@ -1,3 +1,5 @@
     4.4 +#
     4.5 +# @(#)mapfile-vers	1.32 07/10/25 16:47:36
     4.6  #
     4.7  
     4.8  #
     4.9 @@ -75,6 +77,11 @@
    4.10  		JVM_DesiredAssertionStatus;
    4.11  		JVM_DisableCompiler;
    4.12  		JVM_DoPrivileged;
    4.13 +		JVM_DTraceGetVersion;
    4.14 +		JVM_DTraceActivate;
    4.15 +		JVM_DTraceIsProbeEnabled;
    4.16 +		JVM_DTraceIsSupported;
    4.17 +		JVM_DTraceDispose;
    4.18  		JVM_DumpAllStacks;
    4.19  		JVM_DumpThreads;
    4.20  		JVM_EnableCompiler;
     5.1 --- a/src/cpu/sparc/vm/nativeInst_sparc.cpp	Wed Apr 16 17:36:29 2008 -0400
     5.2 +++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Thu Apr 17 22:18:15 2008 -0400
     5.3 @@ -26,6 +26,10 @@
     5.4  # include "incls/_nativeInst_sparc.cpp.incl"
     5.5  
     5.6  
     5.7 +bool NativeInstruction::is_dtrace_trap() {
     5.8 +  return !is_nop();
     5.9 +}
    5.10 +
    5.11  void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) {
    5.12    ResourceMark rm;
    5.13    CodeBuffer buf(instaddr, 10 * BytesPerInstWord );
     6.1 --- a/src/cpu/sparc/vm/nativeInst_sparc.hpp	Wed Apr 16 17:36:29 2008 -0400
     6.2 +++ b/src/cpu/sparc/vm/nativeInst_sparc.hpp	Thu Apr 17 22:18:15 2008 -0400
     6.3 @@ -43,6 +43,7 @@
     6.4      nop_instruction_size        =    4
     6.5    };
     6.6  
     6.7 +  bool is_dtrace_trap();
     6.8    bool is_nop()                        { return long_at(0) == nop_instruction(); }
     6.9    bool is_call()                       { return is_op(long_at(0), Assembler::call_op); }
    6.10    bool is_sethi()                      { return (is_op2(long_at(0), Assembler::sethi_op2)
     7.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Apr 16 17:36:29 2008 -0400
     7.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Apr 17 22:18:15 2008 -0400
     7.3 @@ -1637,7 +1637,7 @@
     7.4      }
     7.5    } else if (dst.is_single_phys_reg()) {
     7.6      if (src.is_adjacent_aligned_on_stack(2)) {
     7.7 -      __ ldd(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register());
     7.8 +      __ ld_long(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register());
     7.9      } else {
    7.10        // dst is a single reg.
    7.11        // Remember lo is low address not msb for stack slots
    7.12 @@ -2501,6 +2501,551 @@
    7.13  
    7.14  }
    7.15  
    7.16 +#ifdef HAVE_DTRACE_H
    7.17 +// ---------------------------------------------------------------------------
    7.18 +// Generate a dtrace nmethod for a given signature.  The method takes arguments
    7.19 +// in the Java compiled code convention, marshals them to the native
    7.20 +// abi and then leaves nops at the position you would expect to call a native
    7.21 +// function. When the probe is enabled the nops are replaced with a trap
    7.22 +// instruction that dtrace inserts and the trace will cause a notification
    7.23 +// to dtrace.
    7.24 +//
    7.25 +// The probes are only able to take primitive types and java/lang/String as
    7.26 +// arguments.  No other java types are allowed. Strings are converted to utf8
    7.27 +// strings so that from dtrace point of view java strings are converted to C
    7.28 +// strings. There is an arbitrary fixed limit on the total space that a method
    7.29 +// can use for converting the strings. (256 chars per string in the signature).
    7.30 +// So any java string larger then this is truncated.
    7.31 +
    7.32 +static int  fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 };
    7.33 +static bool offsets_initialized = false;
    7.34 +
    7.35 +static VMRegPair reg64_to_VMRegPair(Register r) {
    7.36 +  VMRegPair ret;
    7.37 +  if (wordSize == 8) {
    7.38 +    ret.set2(r->as_VMReg());
    7.39 +  } else {
    7.40 +    ret.set_pair(r->successor()->as_VMReg(), r->as_VMReg());
    7.41 +  }
    7.42 +  return ret;
    7.43 +}
    7.44 +
    7.45 +
    7.46 +nmethod *SharedRuntime::generate_dtrace_nmethod(
    7.47 +    MacroAssembler *masm, methodHandle method) {
    7.48 +
    7.49 +
    7.50 +  // generate_dtrace_nmethod is guarded by a mutex so we are sure to
    7.51 +  // be single threaded in this method.
    7.52 +  assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be");
    7.53 +
    7.54 +  // Fill in the signature array, for the calling-convention call.
    7.55 +  int total_args_passed = method->size_of_parameters();
    7.56 +
    7.57 +  BasicType* in_sig_bt  = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
    7.58 +  VMRegPair  *in_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
    7.59 +
    7.60 +  // The signature we are going to use for the trap that dtrace will see
    7.61 +  // java/lang/String is converted. We drop "this" and any other object
    7.62 +  // is converted to NULL.  (A one-slot java/lang/Long object reference
    7.63 +  // is converted to a two-slot long, which is why we double the allocation).
    7.64 +  BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2);
    7.65 +  VMRegPair* out_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2);
    7.66 +
    7.67 +  int i=0;
    7.68 +  int total_strings = 0;
    7.69 +  int first_arg_to_pass = 0;
    7.70 +  int total_c_args = 0;
    7.71 +  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
    7.72 +
    7.73 +  // Skip the receiver as dtrace doesn't want to see it
    7.74 +  if( !method->is_static() ) {
    7.75 +    in_sig_bt[i++] = T_OBJECT;
    7.76 +    first_arg_to_pass = 1;
    7.77 +  }
    7.78 +
    7.79 +  SignatureStream ss(method->signature());
    7.80 +  for ( ; !ss.at_return_type(); ss.next()) {
    7.81 +    BasicType bt = ss.type();
    7.82 +    in_sig_bt[i++] = bt;  // Collect remaining bits of signature
    7.83 +    out_sig_bt[total_c_args++] = bt;
    7.84 +    if( bt == T_OBJECT) {
    7.85 +      symbolOop s = ss.as_symbol_or_null();
    7.86 +      if (s == vmSymbols::java_lang_String()) {
    7.87 +        total_strings++;
    7.88 +        out_sig_bt[total_c_args-1] = T_ADDRESS;
    7.89 +      } else if (s == vmSymbols::java_lang_Boolean() ||
    7.90 +                 s == vmSymbols::java_lang_Byte()) {
    7.91 +        out_sig_bt[total_c_args-1] = T_BYTE;
    7.92 +      } else if (s == vmSymbols::java_lang_Character() ||
    7.93 +                 s == vmSymbols::java_lang_Short()) {
    7.94 +        out_sig_bt[total_c_args-1] = T_SHORT;
    7.95 +      } else if (s == vmSymbols::java_lang_Integer() ||
    7.96 +                 s == vmSymbols::java_lang_Float()) {
    7.97 +        out_sig_bt[total_c_args-1] = T_INT;
    7.98 +      } else if (s == vmSymbols::java_lang_Long() ||
    7.99 +                 s == vmSymbols::java_lang_Double()) {
   7.100 +        out_sig_bt[total_c_args-1] = T_LONG;
   7.101 +        out_sig_bt[total_c_args++] = T_VOID;
   7.102 +      }
   7.103 +    } else if ( bt == T_LONG || bt == T_DOUBLE ) {
   7.104 +      in_sig_bt[i++] = T_VOID;   // Longs & doubles take 2 Java slots
   7.105 +      // We convert double to long
   7.106 +      out_sig_bt[total_c_args-1] = T_LONG;
   7.107 +      out_sig_bt[total_c_args++] = T_VOID;
   7.108 +    } else if ( bt == T_FLOAT) {
   7.109 +      // We convert float to int
   7.110 +      out_sig_bt[total_c_args-1] = T_INT;
   7.111 +    }
   7.112 +  }
   7.113 +
   7.114 +  assert(i==total_args_passed, "validly parsed signature");
   7.115 +
   7.116 +  // Now get the compiled-Java layout as input arguments
   7.117 +  int comp_args_on_stack;
   7.118 +  comp_args_on_stack = SharedRuntime::java_calling_convention(
   7.119 +      in_sig_bt, in_regs, total_args_passed, false);
   7.120 +
   7.121 +  // We have received a description of where all the java arg are located
   7.122 +  // on entry to the wrapper. We need to convert these args to where
   7.123 +  // the a  native (non-jni) function would expect them. To figure out
   7.124 +  // where they go we convert the java signature to a C signature and remove
   7.125 +  // T_VOID for any long/double we might have received.
   7.126 +
   7.127 +
   7.128 +  // Now figure out where the args must be stored and how much stack space
   7.129 +  // they require (neglecting out_preserve_stack_slots but space for storing
   7.130 +  // the 1st six register arguments). It's weird see int_stk_helper.
   7.131 +  //
   7.132 +  int out_arg_slots;
   7.133 +  out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args);
   7.134 +
   7.135 +  // Calculate the total number of stack slots we will need.
   7.136 +
   7.137 +  // First count the abi requirement plus all of the outgoing args
   7.138 +  int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
   7.139 +
   7.140 +  // Plus a temp for possible converion of float/double/long register args
   7.141 +
   7.142 +  int conversion_temp = stack_slots;
   7.143 +  stack_slots += 2;
   7.144 +
   7.145 +
   7.146 +  // Now space for the string(s) we must convert
   7.147 +
   7.148 +  int string_locs = stack_slots;
   7.149 +  stack_slots += total_strings *
   7.150 +                   (max_dtrace_string_size / VMRegImpl::stack_slot_size);
   7.151 +
   7.152 +  // Ok The space we have allocated will look like:
   7.153 +  //
   7.154 +  //
   7.155 +  // FP-> |                     |
   7.156 +  //      |---------------------|
   7.157 +  //      | string[n]           |
   7.158 +  //      |---------------------| <- string_locs[n]
   7.159 +  //      | string[n-1]         |
   7.160 +  //      |---------------------| <- string_locs[n-1]
   7.161 +  //      | ...                 |
   7.162 +  //      | ...                 |
   7.163 +  //      |---------------------| <- string_locs[1]
   7.164 +  //      | string[0]           |
   7.165 +  //      |---------------------| <- string_locs[0]
   7.166 +  //      | temp                |
   7.167 +  //      |---------------------| <- conversion_temp
   7.168 +  //      | outbound memory     |
   7.169 +  //      | based arguments     |
   7.170 +  //      |                     |
   7.171 +  //      |---------------------|
   7.172 +  //      |                     |
   7.173 +  // SP-> | out_preserved_slots |
   7.174 +  //
   7.175 +  //
   7.176 +
   7.177 +  // Now compute actual number of stack words we need rounding to make
   7.178 +  // stack properly aligned.
   7.179 +  stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word);
   7.180 +
   7.181 +  int stack_size = stack_slots * VMRegImpl::stack_slot_size;
   7.182 +
   7.183 +  intptr_t start = (intptr_t)__ pc();
   7.184 +
   7.185 +  // First thing make an ic check to see if we should even be here
   7.186 +
   7.187 +  {
   7.188 +    Label L;
   7.189 +    const Register temp_reg = G3_scratch;
   7.190 +    Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub());
   7.191 +    __ verify_oop(O0);
   7.192 +    __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg);
   7.193 +    __ cmp(temp_reg, G5_inline_cache_reg);
   7.194 +    __ brx(Assembler::equal, true, Assembler::pt, L);
   7.195 +    __ delayed()->nop();
   7.196 +
   7.197 +    __ jump_to(ic_miss, 0);
   7.198 +    __ delayed()->nop();
   7.199 +    __ align(CodeEntryAlignment);
   7.200 +    __ bind(L);
   7.201 +  }
   7.202 +
   7.203 +  int vep_offset = ((intptr_t)__ pc()) - start;
   7.204 +
   7.205 +
   7.206 +  // The instruction at the verified entry point must be 5 bytes or longer
   7.207 +  // because it can be patched on the fly by make_non_entrant. The stack bang
   7.208 +  // instruction fits that requirement.
   7.209 +
   7.210 +  // Generate stack overflow check before creating frame
   7.211 +  __ generate_stack_overflow_check(stack_size);
   7.212 +
   7.213 +  assert(((intptr_t)__ pc() - start - vep_offset) >= 5,
   7.214 +         "valid size for make_non_entrant");
   7.215 +
   7.216 +  // Generate a new frame for the wrapper.
   7.217 +  __ save(SP, -stack_size, SP);
   7.218 +
   7.219 +  // Frame is now completed as far a size and linkage.
   7.220 +
   7.221 +  int frame_complete = ((intptr_t)__ pc()) - start;
   7.222 +
   7.223 +#ifdef ASSERT
   7.224 +  bool reg_destroyed[RegisterImpl::number_of_registers];
   7.225 +  bool freg_destroyed[FloatRegisterImpl::number_of_registers];
   7.226 +  for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) {
   7.227 +    reg_destroyed[r] = false;
   7.228 +  }
   7.229 +  for ( int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++ ) {
   7.230 +    freg_destroyed[f] = false;
   7.231 +  }
   7.232 +
   7.233 +#endif /* ASSERT */
   7.234 +
   7.235 +  VMRegPair zero;
   7.236 +  zero.set2(G0->as_VMReg());
   7.237 +
   7.238 +  int c_arg, j_arg;
   7.239 +
   7.240 +  Register conversion_off = noreg;
   7.241 +
   7.242 +  for (j_arg = first_arg_to_pass, c_arg = 0 ;
   7.243 +       j_arg < total_args_passed ; j_arg++, c_arg++ ) {
   7.244 +
   7.245 +    VMRegPair src = in_regs[j_arg];
   7.246 +    VMRegPair dst = out_regs[c_arg];
   7.247 +
   7.248 +#ifdef ASSERT
   7.249 +    if (src.first()->is_Register()) {
   7.250 +      assert(!reg_destroyed[src.first()->as_Register()->encoding()], "ack!");
   7.251 +    } else if (src.first()->is_FloatRegister()) {
   7.252 +      assert(!freg_destroyed[src.first()->as_FloatRegister()->encoding(
   7.253 +                                               FloatRegisterImpl::S)], "ack!");
   7.254 +    }
   7.255 +    if (dst.first()->is_Register()) {
   7.256 +      reg_destroyed[dst.first()->as_Register()->encoding()] = true;
   7.257 +    } else if (dst.first()->is_FloatRegister()) {
   7.258 +      freg_destroyed[dst.first()->as_FloatRegister()->encoding(
   7.259 +                                                 FloatRegisterImpl::S)] = true;
   7.260 +    }
   7.261 +#endif /* ASSERT */
   7.262 +
   7.263 +    switch (in_sig_bt[j_arg]) {
   7.264 +      case T_ARRAY:
   7.265 +      case T_OBJECT:
   7.266 +        {
   7.267 +          if (out_sig_bt[c_arg] == T_BYTE  || out_sig_bt[c_arg] == T_SHORT ||
   7.268 +              out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) {
   7.269 +            // need to unbox a one-slot value
   7.270 +            Register in_reg = L0;
   7.271 +            Register tmp = L2;
   7.272 +            if ( src.first()->is_reg() ) {
   7.273 +              in_reg = src.first()->as_Register();
   7.274 +            } else {
   7.275 +              assert(Assembler::is_simm13(reg2offset(src.first()) + STACK_BIAS),
   7.276 +                     "must be");
   7.277 +              __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, in_reg);
   7.278 +            }
   7.279 +            // If the final destination is an acceptable register
   7.280 +            if ( dst.first()->is_reg() ) {
   7.281 +              if ( dst.is_single_phys_reg() || out_sig_bt[c_arg] != T_LONG ) {
   7.282 +                tmp = dst.first()->as_Register();
   7.283 +              }
   7.284 +            }
   7.285 +
   7.286 +            Label skipUnbox;
   7.287 +            if ( wordSize == 4 && out_sig_bt[c_arg] == T_LONG ) {
   7.288 +              __ mov(G0, tmp->successor());
   7.289 +            }
   7.290 +            __ br_null(in_reg, true, Assembler::pn, skipUnbox);
   7.291 +            __ delayed()->mov(G0, tmp);
   7.292 +
   7.293 +            switch (out_sig_bt[c_arg]) {
   7.294 +                case T_BYTE:
   7.295 +                  __ ldub(in_reg, box_offset, tmp); break;
   7.296 +                case T_SHORT:
   7.297 +                  __ lduh(in_reg, box_offset, tmp); break;
   7.298 +                case T_INT:
   7.299 +                  __ ld(in_reg, box_offset, tmp); break;
   7.300 +                case T_LONG:
   7.301 +                  __ ld_long(in_reg, box_offset, tmp); break;
   7.302 +                default: ShouldNotReachHere();
   7.303 +            }
   7.304 +
   7.305 +            __ bind(skipUnbox);
   7.306 +            // If tmp wasn't final destination copy to final destination
   7.307 +            if (tmp == L2) {
   7.308 +              VMRegPair tmp_as_VM = reg64_to_VMRegPair(L2);
   7.309 +              if (out_sig_bt[c_arg] == T_LONG) {
   7.310 +                long_move(masm, tmp_as_VM, dst);
   7.311 +              } else {
   7.312 +                move32_64(masm, tmp_as_VM, out_regs[c_arg]);
   7.313 +              }
   7.314 +            }
   7.315 +            if (out_sig_bt[c_arg] == T_LONG) {
   7.316 +              assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
   7.317 +              ++c_arg; // move over the T_VOID to keep the loop indices in sync
   7.318 +            }
   7.319 +          } else if (out_sig_bt[c_arg] == T_ADDRESS) {
   7.320 +            Register s =
   7.321 +                src.first()->is_reg() ? src.first()->as_Register() : L2;
   7.322 +            Register d =
   7.323 +                dst.first()->is_reg() ? dst.first()->as_Register() : L2;
   7.324 +
   7.325 +            // We store the oop now so that the conversion pass can reach
   7.326 +            // while in the inner frame. This will be the only store if
   7.327 +            // the oop is NULL.
   7.328 +            if (s != L2) {
   7.329 +              // src is register
   7.330 +              if (d != L2) {
   7.331 +                // dst is register
   7.332 +                __ mov(s, d);
   7.333 +              } else {
   7.334 +                assert(Assembler::is_simm13(reg2offset(dst.first()) +
   7.335 +                          STACK_BIAS), "must be");
   7.336 +                __ st_ptr(s, SP, reg2offset(dst.first()) + STACK_BIAS);
   7.337 +              }
   7.338 +            } else {
   7.339 +                // src not a register
   7.340 +                assert(Assembler::is_simm13(reg2offset(src.first()) +
   7.341 +                           STACK_BIAS), "must be");
   7.342 +                __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, d);
   7.343 +                if (d == L2) {
   7.344 +                  assert(Assembler::is_simm13(reg2offset(dst.first()) +
   7.345 +                             STACK_BIAS), "must be");
   7.346 +                  __ st_ptr(d, SP, reg2offset(dst.first()) + STACK_BIAS);
   7.347 +                }
   7.348 +            }
   7.349 +          } else if (out_sig_bt[c_arg] != T_VOID) {
   7.350 +            // Convert the arg to NULL
   7.351 +            if (dst.first()->is_reg()) {
   7.352 +              __ mov(G0, dst.first()->as_Register());
   7.353 +            } else {
   7.354 +              assert(Assembler::is_simm13(reg2offset(dst.first()) +
   7.355 +                         STACK_BIAS), "must be");
   7.356 +              __ st_ptr(G0, SP, reg2offset(dst.first()) + STACK_BIAS);
   7.357 +            }
   7.358 +          }
   7.359 +        }
   7.360 +        break;
   7.361 +      case T_VOID:
   7.362 +        break;
   7.363 +
   7.364 +      case T_FLOAT:
   7.365 +        if (src.first()->is_stack()) {
   7.366 +          // Stack to stack/reg is simple
   7.367 +          move32_64(masm, src, dst);
   7.368 +        } else {
   7.369 +          if (dst.first()->is_reg()) {
   7.370 +            // freg -> reg
   7.371 +            int off =
   7.372 +              STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size;
   7.373 +            Register d = dst.first()->as_Register();
   7.374 +            if (Assembler::is_simm13(off)) {
   7.375 +              __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(),
   7.376 +                     SP, off);
   7.377 +              __ ld(SP, off, d);
   7.378 +            } else {
   7.379 +              if (conversion_off == noreg) {
   7.380 +                __ set(off, L6);
   7.381 +                conversion_off = L6;
   7.382 +              }
   7.383 +              __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(),
   7.384 +                     SP, conversion_off);
   7.385 +              __ ld(SP, conversion_off , d);
   7.386 +            }
   7.387 +          } else {
   7.388 +            // freg -> mem
   7.389 +            int off = STACK_BIAS + reg2offset(dst.first());
   7.390 +            if (Assembler::is_simm13(off)) {
   7.391 +              __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(),
   7.392 +                     SP, off);
   7.393 +            } else {
   7.394 +              if (conversion_off == noreg) {
   7.395 +                __ set(off, L6);
   7.396 +                conversion_off = L6;
   7.397 +              }
   7.398 +              __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(),
   7.399 +                     SP, conversion_off);
   7.400 +            }
   7.401 +          }
   7.402 +        }
   7.403 +        break;
   7.404 +
   7.405 +      case T_DOUBLE:
   7.406 +        assert( j_arg + 1 < total_args_passed &&
   7.407 +                in_sig_bt[j_arg + 1] == T_VOID &&
   7.408 +                out_sig_bt[c_arg+1] == T_VOID, "bad arg list");
   7.409 +        if (src.first()->is_stack()) {
   7.410 +          // Stack to stack/reg is simple
   7.411 +          long_move(masm, src, dst);
   7.412 +        } else {
   7.413 +          Register d = dst.first()->is_reg() ? dst.first()->as_Register() : L2;
   7.414 +
   7.415 +          // Destination could be an odd reg on 32bit in which case
   7.416 +          // we can't load direct to the destination.
   7.417 +
   7.418 +          if (!d->is_even() && wordSize == 4) {
   7.419 +            d = L2;
   7.420 +          }
   7.421 +          int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size;
   7.422 +          if (Assembler::is_simm13(off)) {
   7.423 +            __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(),
   7.424 +                   SP, off);
   7.425 +            __ ld_long(SP, off, d);
   7.426 +          } else {
   7.427 +            if (conversion_off == noreg) {
   7.428 +              __ set(off, L6);
   7.429 +              conversion_off = L6;
   7.430 +            }
   7.431 +            __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(),
   7.432 +                   SP, conversion_off);
   7.433 +            __ ld_long(SP, conversion_off, d);
   7.434 +          }
   7.435 +          if (d == L2) {
   7.436 +            long_move(masm, reg64_to_VMRegPair(L2), dst);
   7.437 +          }
   7.438 +        }
   7.439 +        break;
   7.440 +
   7.441 +      case T_LONG :
   7.442 +        // 32bit can't do a split move of something like g1 -> O0, O1
   7.443 +        // so use a memory temp
   7.444 +        if (src.is_single_phys_reg() && wordSize == 4) {
   7.445 +          Register tmp = L2;
   7.446 +          if (dst.first()->is_reg() &&
   7.447 +              (wordSize == 8 || dst.first()->as_Register()->is_even())) {
   7.448 +            tmp = dst.first()->as_Register();
   7.449 +          }
   7.450 +
   7.451 +          int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size;
   7.452 +          if (Assembler::is_simm13(off)) {
   7.453 +            __ stx(src.first()->as_Register(), SP, off);
   7.454 +            __ ld_long(SP, off, tmp);
   7.455 +          } else {
   7.456 +            if (conversion_off == noreg) {
   7.457 +              __ set(off, L6);
   7.458 +              conversion_off = L6;
   7.459 +            }
   7.460 +            __ stx(src.first()->as_Register(), SP, conversion_off);
   7.461 +            __ ld_long(SP, conversion_off, tmp);
   7.462 +          }
   7.463 +
   7.464 +          if (tmp == L2) {
   7.465 +            long_move(masm, reg64_to_VMRegPair(L2), dst);
   7.466 +          }
   7.467 +        } else {
   7.468 +          long_move(masm, src, dst);
   7.469 +        }
   7.470 +        break;
   7.471 +
   7.472 +      case T_ADDRESS: assert(false, "found T_ADDRESS in java args");
   7.473 +
   7.474 +      default:
   7.475 +        move32_64(masm, src, dst);
   7.476 +    }
   7.477 +  }
   7.478 +
   7.479 +
   7.480 +  // If we have any strings we must store any register based arg to the stack
   7.481 +  // This includes any still live xmm registers too.
   7.482 +
   7.483 +  if (total_strings > 0 ) {
   7.484 +
   7.485 +    // protect all the arg registers
   7.486 +    __ save_frame(0);
   7.487 +    __ mov(G2_thread, L7_thread_cache);
   7.488 +    const Register L2_string_off = L2;
   7.489 +
   7.490 +    // Get first string offset
   7.491 +    __ set(string_locs * VMRegImpl::stack_slot_size, L2_string_off);
   7.492 +
   7.493 +    for (c_arg = 0 ; c_arg < total_c_args ; c_arg++ ) {
   7.494 +      if (out_sig_bt[c_arg] == T_ADDRESS) {
   7.495 +
   7.496 +        VMRegPair dst = out_regs[c_arg];
   7.497 +        const Register d = dst.first()->is_reg() ?
   7.498 +            dst.first()->as_Register()->after_save() : noreg;
   7.499 +
   7.500 +        // It's a string the oop and it was already copied to the out arg
   7.501 +        // position
   7.502 +        if (d != noreg) {
   7.503 +          __ mov(d, O0);
   7.504 +        } else {
   7.505 +          assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS),
   7.506 +                 "must be");
   7.507 +          __ ld_ptr(FP,  reg2offset(dst.first()) + STACK_BIAS, O0);
   7.508 +        }
   7.509 +        Label skip;
   7.510 +
   7.511 +        __ br_null(O0, false, Assembler::pn, skip);
   7.512 +        __ delayed()->add(FP, L2_string_off, O1);
   7.513 +
   7.514 +        if (d != noreg) {
   7.515 +          __ mov(O1, d);
   7.516 +        } else {
   7.517 +          assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS),
   7.518 +                 "must be");
   7.519 +          __ st_ptr(O1, FP,  reg2offset(dst.first()) + STACK_BIAS);
   7.520 +        }
   7.521 +
   7.522 +        __ call(CAST_FROM_FN_PTR(address, SharedRuntime::get_utf),
   7.523 +                relocInfo::runtime_call_type);
   7.524 +        __ delayed()->add(L2_string_off, max_dtrace_string_size, L2_string_off);
   7.525 +
   7.526 +        __ bind(skip);
   7.527 +
   7.528 +      }
   7.529 +
   7.530 +    }
   7.531 +    __ mov(L7_thread_cache, G2_thread);
   7.532 +    __ restore();
   7.533 +
   7.534 +  }
   7.535 +
   7.536 +
   7.537 +  // Ok now we are done. Need to place the nop that dtrace wants in order to
   7.538 +  // patch in the trap
   7.539 +
   7.540 +  int patch_offset = ((intptr_t)__ pc()) - start;
   7.541 +
   7.542 +  __ nop();
   7.543 +
   7.544 +
   7.545 +  // Return
   7.546 +
   7.547 +  __ ret();
   7.548 +  __ delayed()->restore();
   7.549 +
   7.550 +  __ flush();
   7.551 +
   7.552 +  nmethod *nm = nmethod::new_dtrace_nmethod(
   7.553 +      method, masm->code(), vep_offset, patch_offset, frame_complete,
   7.554 +      stack_slots / VMRegImpl::slots_per_word);
   7.555 +  return nm;
   7.556 +
   7.557 +}
   7.558 +
   7.559 +#endif // HAVE_DTRACE_H
   7.560 +
   7.561  // this function returns the adjust size (in number of words) to a c2i adapter
   7.562  // activation for use during deoptimization
   7.563  int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) {
     8.1 --- a/src/cpu/x86/vm/nativeInst_x86.cpp	Wed Apr 16 17:36:29 2008 -0400
     8.2 +++ b/src/cpu/x86/vm/nativeInst_x86.cpp	Thu Apr 17 22:18:15 2008 -0400
     8.3 @@ -472,3 +472,7 @@
     8.4    else
     8.5      return addr_at(0) + length + sbyte_at(offset);
     8.6  }
     8.7 +
     8.8 +bool NativeInstruction::is_dtrace_trap() {
     8.9 +  return (*(int32_t*)this & 0xff) == 0xcc;
    8.10 +}
     9.1 --- a/src/cpu/x86/vm/nativeInst_x86.hpp	Wed Apr 16 17:36:29 2008 -0400
     9.2 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp	Thu Apr 17 22:18:15 2008 -0400
     9.3 @@ -50,6 +50,7 @@
     9.4    };
     9.5  
     9.6    bool is_nop()                        { return ubyte_at(0) == nop_instruction_code; }
     9.7 +  bool is_dtrace_trap();
     9.8    inline bool is_call();
     9.9    inline bool is_illegal();
    9.10    inline bool is_return();
    10.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Apr 16 17:36:29 2008 -0400
    10.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Apr 17 22:18:15 2008 -0400
    10.3 @@ -1880,6 +1880,379 @@
    10.4  
    10.5  }
    10.6  
    10.7 +#ifdef HAVE_DTRACE_H
    10.8 +// ---------------------------------------------------------------------------
    10.9 +// Generate a dtrace nmethod for a given signature.  The method takes arguments
   10.10 +// in the Java compiled code convention, marshals them to the native
   10.11 +// abi and then leaves nops at the position you would expect to call a native
   10.12 +// function. When the probe is enabled the nops are replaced with a trap
   10.13 +// instruction that dtrace inserts and the trace will cause a notification
   10.14 +// to dtrace.
   10.15 +//
   10.16 +// The probes are only able to take primitive types and java/lang/String as
   10.17 +// arguments.  No other java types are allowed. Strings are converted to utf8
   10.18 +// strings so that from dtrace point of view java strings are converted to C
   10.19 +// strings. There is an arbitrary fixed limit on the total space that a method
   10.20 +// can use for converting the strings. (256 chars per string in the signature).
   10.21 +// So any java string larger then this is truncated.
   10.22 +
   10.23 +nmethod *SharedRuntime::generate_dtrace_nmethod(
   10.24 +    MacroAssembler *masm, methodHandle method) {
   10.25 +
   10.26 +  // generate_dtrace_nmethod is guarded by a mutex so we are sure to
   10.27 +  // be single threaded in this method.
   10.28 +  assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be");
   10.29 +
   10.30 +  // Fill in the signature array, for the calling-convention call.
   10.31 +  int total_args_passed = method->size_of_parameters();
   10.32 +
   10.33 +  BasicType* in_sig_bt  = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
   10.34 +  VMRegPair  *in_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
   10.35 +
   10.36 +  // The signature we are going to use for the trap that dtrace will see
   10.37 +  // java/lang/String is converted. We drop "this" and any other object
   10.38 +  // is converted to NULL.  (A one-slot java/lang/Long object reference
   10.39 +  // is converted to a two-slot long, which is why we double the allocation).
   10.40 +  BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2);
   10.41 +  VMRegPair* out_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2);
   10.42 +
   10.43 +  int i=0;
   10.44 +  int total_strings = 0;
   10.45 +  int first_arg_to_pass = 0;
   10.46 +  int total_c_args = 0;
   10.47 +  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
   10.48 +
   10.49 +  if( !method->is_static() ) {  // Pass in receiver first
   10.50 +    in_sig_bt[i++] = T_OBJECT;
   10.51 +    first_arg_to_pass = 1;
   10.52 +  }
   10.53 +
   10.54 +  // We need to convert the java args to where a native (non-jni) function
   10.55 +  // would expect them. To figure out where they go we convert the java
   10.56 +  // signature to a C signature.
   10.57 +
   10.58 +  SignatureStream ss(method->signature());
   10.59 +  for ( ; !ss.at_return_type(); ss.next()) {
   10.60 +    BasicType bt = ss.type();
   10.61 +    in_sig_bt[i++] = bt;  // Collect remaining bits of signature
   10.62 +    out_sig_bt[total_c_args++] = bt;
   10.63 +    if( bt == T_OBJECT) {
   10.64 +      symbolOop s = ss.as_symbol_or_null();
   10.65 +      if (s == vmSymbols::java_lang_String()) {
   10.66 +        total_strings++;
   10.67 +        out_sig_bt[total_c_args-1] = T_ADDRESS;
   10.68 +      } else if (s == vmSymbols::java_lang_Boolean() ||
   10.69 +                 s == vmSymbols::java_lang_Character() ||
   10.70 +                 s == vmSymbols::java_lang_Byte() ||
   10.71 +                 s == vmSymbols::java_lang_Short() ||
   10.72 +                 s == vmSymbols::java_lang_Integer() ||
   10.73 +                 s == vmSymbols::java_lang_Float()) {
   10.74 +        out_sig_bt[total_c_args-1] = T_INT;
   10.75 +      } else if (s == vmSymbols::java_lang_Long() ||
   10.76 +                 s == vmSymbols::java_lang_Double()) {
   10.77 +        out_sig_bt[total_c_args-1] = T_LONG;
   10.78 +        out_sig_bt[total_c_args++] = T_VOID;
   10.79 +      }
   10.80 +    } else if ( bt == T_LONG || bt == T_DOUBLE ) {
   10.81 +      in_sig_bt[i++] = T_VOID;   // Longs & doubles take 2 Java slots
   10.82 +      out_sig_bt[total_c_args++] = T_VOID;
   10.83 +    }
   10.84 +  }
   10.85 +
   10.86 +  assert(i==total_args_passed, "validly parsed signature");
   10.87 +
   10.88 +  // Now get the compiled-Java layout as input arguments
   10.89 +  int comp_args_on_stack;
   10.90 +  comp_args_on_stack = SharedRuntime::java_calling_convention(
   10.91 +      in_sig_bt, in_regs, total_args_passed, false);
   10.92 +
   10.93 +  // Now figure out where the args must be stored and how much stack space
   10.94 +  // they require (neglecting out_preserve_stack_slots).
   10.95 +
   10.96 +  int out_arg_slots;
   10.97 +  out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args);
   10.98 +
   10.99 +  // Calculate the total number of stack slots we will need.
  10.100 +
  10.101 +  // First count the abi requirement plus all of the outgoing args
  10.102 +  int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
  10.103 +
  10.104 +  // Now space for the string(s) we must convert
  10.105 +
  10.106 +  int* string_locs   = NEW_RESOURCE_ARRAY(int, total_strings + 1);
  10.107 +  for (i = 0; i < total_strings ; i++) {
  10.108 +    string_locs[i] = stack_slots;
  10.109 +    stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size;
  10.110 +  }
  10.111 +
  10.112 +  // + 2 for return address (which we own) and saved rbp,
  10.113 +
  10.114 +  stack_slots += 2;
  10.115 +
  10.116 +  // Ok The space we have allocated will look like:
  10.117 +  //
  10.118 +  //
  10.119 +  // FP-> |                     |
  10.120 +  //      |---------------------|
  10.121 +  //      | string[n]           |
  10.122 +  //      |---------------------| <- string_locs[n]
  10.123 +  //      | string[n-1]         |
  10.124 +  //      |---------------------| <- string_locs[n-1]
  10.125 +  //      | ...                 |
  10.126 +  //      | ...                 |
  10.127 +  //      |---------------------| <- string_locs[1]
  10.128 +  //      | string[0]           |
  10.129 +  //      |---------------------| <- string_locs[0]
  10.130 +  //      | outbound memory     |
  10.131 +  //      | based arguments     |
  10.132 +  //      |                     |
  10.133 +  //      |---------------------|
  10.134 +  //      |                     |
  10.135 +  // SP-> | out_preserved_slots |
  10.136 +  //
  10.137 +  //
  10.138 +
  10.139 +  // Now compute actual number of stack words we need rounding to make
  10.140 +  // stack properly aligned.
  10.141 +  stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word);
  10.142 +
  10.143 +  int stack_size = stack_slots * VMRegImpl::stack_slot_size;
  10.144 +
  10.145 +  intptr_t start = (intptr_t)__ pc();
  10.146 +
  10.147 +  // First thing make an ic check to see if we should even be here
  10.148 +
  10.149 +  // We are free to use all registers as temps without saving them and
  10.150 +  // restoring them except rbp. rbp, is the only callee save register
  10.151 +  // as far as the interpreter and the compiler(s) are concerned.
  10.152 +
  10.153 +  const Register ic_reg = rax;
  10.154 +  const Register receiver = rcx;
  10.155 +  Label hit;
  10.156 +  Label exception_pending;
  10.157 +
  10.158 +
  10.159 +  __ verify_oop(receiver);
  10.160 +  __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
  10.161 +  __ jcc(Assembler::equal, hit);
  10.162 +
  10.163 +  __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
  10.164 +
  10.165 +  // verified entry must be aligned for code patching.
  10.166 +  // and the first 5 bytes must be in the same cache line
  10.167 +  // if we align at 8 then we will be sure 5 bytes are in the same line
  10.168 +  __ align(8);
  10.169 +
  10.170 +  __ bind(hit);
  10.171 +
  10.172 +  int vep_offset = ((intptr_t)__ pc()) - start;
  10.173 +
  10.174 +
  10.175 +  // The instruction at the verified entry point must be 5 bytes or longer
  10.176 +  // because it can be patched on the fly by make_non_entrant. The stack bang
  10.177 +  // instruction fits that requirement.
  10.178 +
  10.179 +  // Generate stack overflow check
  10.180 +
  10.181 +
  10.182 +  if (UseStackBanging) {
  10.183 +    if (stack_size <= StackShadowPages*os::vm_page_size()) {
  10.184 +      __ bang_stack_with_offset(StackShadowPages*os::vm_page_size());
  10.185 +    } else {
  10.186 +      __ movl(rax, stack_size);
  10.187 +      __ bang_stack_size(rax, rbx);
  10.188 +    }
  10.189 +  } else {
  10.190 +    // need a 5 byte instruction to allow MT safe patching to non-entrant
  10.191 +    __ fat_nop();
  10.192 +  }
  10.193 +
  10.194 +  assert(((int)__ pc() - start - vep_offset) >= 5,
  10.195 +         "valid size for make_non_entrant");
  10.196 +
  10.197 +  // Generate a new frame for the wrapper.
  10.198 +  __ enter();
  10.199 +
  10.200 +  // -2 because return address is already present and so is saved rbp,
  10.201 +  if (stack_size - 2*wordSize != 0) {
  10.202 +    __ subl(rsp, stack_size - 2*wordSize);
  10.203 +  }
  10.204 +
  10.205 +  // Frame is now completed as far a size and linkage.
  10.206 +
  10.207 +  int frame_complete = ((intptr_t)__ pc()) - start;
  10.208 +
  10.209 +  // First thing we do store all the args as if we are doing the call.
  10.210 +  // Since the C calling convention is stack based that ensures that
  10.211 +  // all the Java register args are stored before we need to convert any
  10.212 +  // string we might have.
  10.213 +
  10.214 +  int sid = 0;
  10.215 +  int c_arg, j_arg;
  10.216 +  int string_reg = 0;
  10.217 +
  10.218 +  for (j_arg = first_arg_to_pass, c_arg = 0 ;
  10.219 +       j_arg < total_args_passed ; j_arg++, c_arg++ ) {
  10.220 +
  10.221 +    VMRegPair src = in_regs[j_arg];
  10.222 +    VMRegPair dst = out_regs[c_arg];
  10.223 +    assert(dst.first()->is_stack() || in_sig_bt[j_arg] == T_VOID,
  10.224 +           "stack based abi assumed");
  10.225 +
  10.226 +    switch (in_sig_bt[j_arg]) {
  10.227 +
  10.228 +      case T_ARRAY:
  10.229 +      case T_OBJECT:
  10.230 +        if (out_sig_bt[c_arg] == T_ADDRESS) {
  10.231 +          // Any register based arg for a java string after the first
  10.232 +          // will be destroyed by the call to get_utf so we store
  10.233 +          // the original value in the location the utf string address
  10.234 +          // will eventually be stored.
  10.235 +          if (src.first()->is_reg()) {
  10.236 +            if (string_reg++ != 0) {
  10.237 +              simple_move32(masm, src, dst);
  10.238 +            }
  10.239 +          }
  10.240 +        } else if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) {
  10.241 +          // need to unbox a one-word value
  10.242 +          Register in_reg = rax;
  10.243 +          if ( src.first()->is_reg() ) {
  10.244 +            in_reg = src.first()->as_Register();
  10.245 +          } else {
  10.246 +            simple_move32(masm, src, in_reg->as_VMReg());
  10.247 +          }
  10.248 +          Label skipUnbox;
  10.249 +          __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD);
  10.250 +          if ( out_sig_bt[c_arg] == T_LONG ) {
  10.251 +            __ movl(Address(rsp, reg2offset_out(dst.second())), NULL_WORD);
  10.252 +          }
  10.253 +          __ testl(in_reg, in_reg);
  10.254 +          __ jcc(Assembler::zero, skipUnbox);
  10.255 +          assert(dst.first()->is_stack() &&
  10.256 +                 (!dst.second()->is_valid() || dst.second()->is_stack()),
  10.257 +                 "value(s) must go into stack slots");
  10.258 +          if ( out_sig_bt[c_arg] == T_LONG ) {
  10.259 +            __ movl(rbx, Address(in_reg,
  10.260 +                                 box_offset + VMRegImpl::stack_slot_size));
  10.261 +            __ movl(Address(rsp, reg2offset_out(dst.second())), rbx);
  10.262 +          }
  10.263 +          __ movl(in_reg,  Address(in_reg, box_offset));
  10.264 +          __ movl(Address(rsp, reg2offset_out(dst.first())), in_reg);
  10.265 +          __ bind(skipUnbox);
  10.266 +        } else {
  10.267 +          // Convert the arg to NULL
  10.268 +          __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD);
  10.269 +        }
  10.270 +        if (out_sig_bt[c_arg] == T_LONG) {
  10.271 +          assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  10.272 +          ++c_arg; // Move over the T_VOID To keep the loop indices in sync
  10.273 +        }
  10.274 +        break;
  10.275 +
  10.276 +      case T_VOID:
  10.277 +        break;
  10.278 +
  10.279 +      case T_FLOAT:
  10.280 +        float_move(masm, src, dst);
  10.281 +        break;
  10.282 +
  10.283 +      case T_DOUBLE:
  10.284 +        assert( j_arg + 1 < total_args_passed &&
  10.285 +                in_sig_bt[j_arg + 1] == T_VOID, "bad arg list");
  10.286 +        double_move(masm, src, dst);
  10.287 +        break;
  10.288 +
  10.289 +      case T_LONG :
  10.290 +        long_move(masm, src, dst);
  10.291 +        break;
  10.292 +
  10.293 +      case T_ADDRESS: assert(false, "found T_ADDRESS in java args");
  10.294 +
  10.295 +      default:
  10.296 +        simple_move32(masm, src, dst);
  10.297 +    }
  10.298 +  }
  10.299 +
  10.300 +  // Now we must convert any string we have to utf8
  10.301 +  //
  10.302 +
  10.303 +  for (sid = 0, j_arg = first_arg_to_pass, c_arg = 0 ;
  10.304 +       sid < total_strings ; j_arg++, c_arg++ ) {
  10.305 +
  10.306 +    if (out_sig_bt[c_arg] == T_ADDRESS) {
  10.307 +
  10.308 +      Address utf8_addr = Address(
  10.309 +          rsp, string_locs[sid++] * VMRegImpl::stack_slot_size);
  10.310 +      __ leal(rax, utf8_addr);
  10.311 +
  10.312 +      // The first string we find might still be in the original java arg
  10.313 +      // register
  10.314 +      VMReg orig_loc = in_regs[j_arg].first();
  10.315 +      Register string_oop;
  10.316 +
  10.317 +      // This is where the argument will eventually reside
  10.318 +      Address dest = Address(rsp, reg2offset_out(out_regs[c_arg].first()));
  10.319 +
  10.320 +      if (sid == 1 && orig_loc->is_reg()) {
  10.321 +        string_oop = orig_loc->as_Register();
  10.322 +        assert(string_oop != rax, "smashed arg");
  10.323 +      } else {
  10.324 +
  10.325 +        if (orig_loc->is_reg()) {
  10.326 +          // Get the copy of the jls object
  10.327 +          __ movl(rcx, dest);
  10.328 +        } else {
  10.329 +          // arg is still in the original location
  10.330 +          __ movl(rcx, Address(rbp, reg2offset_in(orig_loc)));
  10.331 +        }
  10.332 +        string_oop = rcx;
  10.333 +
  10.334 +      }
  10.335 +      Label nullString;
  10.336 +      __ movl(dest, NULL_WORD);
  10.337 +      __ testl(string_oop, string_oop);
  10.338 +      __ jcc(Assembler::zero, nullString);
  10.339 +
  10.340 +      // Now we can store the address of the utf string as the argument
  10.341 +      __ movl(dest, rax);
  10.342 +
  10.343 +      // And do the conversion
  10.344 +      __ call_VM_leaf(CAST_FROM_FN_PTR(
  10.345 +             address, SharedRuntime::get_utf), string_oop, rax);
  10.346 +      __ bind(nullString);
  10.347 +    }
  10.348 +
  10.349 +    if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) {
  10.350 +      assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  10.351 +      ++c_arg; // Move over the T_VOID To keep the loop indices in sync
  10.352 +    }
  10.353 +  }
  10.354 +
  10.355 +
  10.356 +  // Ok now we are done. Need to place the nop that dtrace wants in order to
  10.357 +  // patch in the trap
  10.358 +
  10.359 +  int patch_offset = ((intptr_t)__ pc()) - start;
  10.360 +
  10.361 +  __ nop();
  10.362 +
  10.363 +
  10.364 +  // Return
  10.365 +
  10.366 +  __ leave();
  10.367 +  __ ret(0);
  10.368 +
  10.369 +  __ flush();
  10.370 +
  10.371 +  nmethod *nm = nmethod::new_dtrace_nmethod(
  10.372 +      method, masm->code(), vep_offset, patch_offset, frame_complete,
  10.373 +      stack_slots / VMRegImpl::slots_per_word);
  10.374 +  return nm;
  10.375 +
  10.376 +}
  10.377 +
  10.378 +#endif // HAVE_DTRACE_H
  10.379 +
  10.380  // this function returns the adjust size (in number of words) to a c2i adapter
  10.381  // activation for use during deoptimization
  10.382  int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) {
    11.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Apr 16 17:36:29 2008 -0400
    11.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Apr 17 22:18:15 2008 -0400
    11.3 @@ -1886,6 +1886,627 @@
    11.4  
    11.5  }
    11.6  
    11.7 +#ifdef HAVE_DTRACE_H
    11.8 +// ---------------------------------------------------------------------------
    11.9 +// Generate a dtrace nmethod for a given signature.  The method takes arguments
   11.10 +// in the Java compiled code convention, marshals them to the native
   11.11 +// abi and then leaves nops at the position you would expect to call a native
   11.12 +// function. When the probe is enabled the nops are replaced with a trap
   11.13 +// instruction that dtrace inserts and the trace will cause a notification
   11.14 +// to dtrace.
   11.15 +//
   11.16 +// The probes are only able to take primitive types and java/lang/String as
   11.17 +// arguments.  No other java types are allowed. Strings are converted to utf8
   11.18 +// strings so that from dtrace point of view java strings are converted to C
   11.19 +// strings. There is an arbitrary fixed limit on the total space that a method
   11.20 +// can use for converting the strings. (256 chars per string in the signature).
   11.21 +// So any java string larger then this is truncated.
   11.22 +
   11.23 +static int  fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 };
   11.24 +static bool offsets_initialized = false;
   11.25 +
   11.26 +
   11.27 +nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm,
   11.28 +                                                methodHandle method) {
   11.29 +
   11.30 +
   11.31 +  // generate_dtrace_nmethod is guarded by a mutex so we are sure to
   11.32 +  // be single threaded in this method.
   11.33 +  assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be");
   11.34 +
   11.35 +  if (!offsets_initialized) {
   11.36 +    fp_offset[c_rarg0->as_VMReg()->value()] = -1 * wordSize;
   11.37 +    fp_offset[c_rarg1->as_VMReg()->value()] = -2 * wordSize;
   11.38 +    fp_offset[c_rarg2->as_VMReg()->value()] = -3 * wordSize;
   11.39 +    fp_offset[c_rarg3->as_VMReg()->value()] = -4 * wordSize;
   11.40 +    fp_offset[c_rarg4->as_VMReg()->value()] = -5 * wordSize;
   11.41 +    fp_offset[c_rarg5->as_VMReg()->value()] = -6 * wordSize;
   11.42 +
   11.43 +    fp_offset[c_farg0->as_VMReg()->value()] = -7 * wordSize;
   11.44 +    fp_offset[c_farg1->as_VMReg()->value()] = -8 * wordSize;
   11.45 +    fp_offset[c_farg2->as_VMReg()->value()] = -9 * wordSize;
   11.46 +    fp_offset[c_farg3->as_VMReg()->value()] = -10 * wordSize;
   11.47 +    fp_offset[c_farg4->as_VMReg()->value()] = -11 * wordSize;
   11.48 +    fp_offset[c_farg5->as_VMReg()->value()] = -12 * wordSize;
   11.49 +    fp_offset[c_farg6->as_VMReg()->value()] = -13 * wordSize;
   11.50 +    fp_offset[c_farg7->as_VMReg()->value()] = -14 * wordSize;
   11.51 +
   11.52 +    offsets_initialized = true;
   11.53 +  }
   11.54 +  // Fill in the signature array, for the calling-convention call.
   11.55 +  int total_args_passed = method->size_of_parameters();
   11.56 +
   11.57 +  BasicType* in_sig_bt  = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
   11.58 +  VMRegPair  *in_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
   11.59 +
   11.60 +  // The signature we are going to use for the trap that dtrace will see
   11.61 +  // java/lang/String is converted. We drop "this" and any other object
   11.62 +  // is converted to NULL.  (A one-slot java/lang/Long object reference
   11.63 +  // is converted to a two-slot long, which is why we double the allocation).
   11.64 +  BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2);
   11.65 +  VMRegPair* out_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2);
   11.66 +
   11.67 +  int i=0;
   11.68 +  int total_strings = 0;
   11.69 +  int first_arg_to_pass = 0;
   11.70 +  int total_c_args = 0;
   11.71 +  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
   11.72 +
   11.73 +  // Skip the receiver as dtrace doesn't want to see it
   11.74 +  if( !method->is_static() ) {
   11.75 +    in_sig_bt[i++] = T_OBJECT;
   11.76 +    first_arg_to_pass = 1;
   11.77 +  }
   11.78 +
   11.79 +  // We need to convert the java args to where a native (non-jni) function
   11.80 +  // would expect them. To figure out where they go we convert the java
   11.81 +  // signature to a C signature.
   11.82 +
   11.83 +  SignatureStream ss(method->signature());
   11.84 +  for ( ; !ss.at_return_type(); ss.next()) {
   11.85 +    BasicType bt = ss.type();
   11.86 +    in_sig_bt[i++] = bt;  // Collect remaining bits of signature
   11.87 +    out_sig_bt[total_c_args++] = bt;
   11.88 +    if( bt == T_OBJECT) {
   11.89 +      symbolOop s = ss.as_symbol_or_null();
   11.90 +      if (s == vmSymbols::java_lang_String()) {
   11.91 +        total_strings++;
   11.92 +        out_sig_bt[total_c_args-1] = T_ADDRESS;
   11.93 +      } else if (s == vmSymbols::java_lang_Boolean() ||
   11.94 +                 s == vmSymbols::java_lang_Character() ||
   11.95 +                 s == vmSymbols::java_lang_Byte() ||
   11.96 +                 s == vmSymbols::java_lang_Short() ||
   11.97 +                 s == vmSymbols::java_lang_Integer() ||
   11.98 +                 s == vmSymbols::java_lang_Float()) {
   11.99 +        out_sig_bt[total_c_args-1] = T_INT;
  11.100 +      } else if (s == vmSymbols::java_lang_Long() ||
  11.101 +                 s == vmSymbols::java_lang_Double()) {
  11.102 +        out_sig_bt[total_c_args-1] = T_LONG;
  11.103 +        out_sig_bt[total_c_args++] = T_VOID;
  11.104 +      }
  11.105 +    } else if ( bt == T_LONG || bt == T_DOUBLE ) {
  11.106 +      in_sig_bt[i++] = T_VOID;   // Longs & doubles take 2 Java slots
  11.107 +      // We convert double to long
  11.108 +      out_sig_bt[total_c_args-1] = T_LONG;
  11.109 +      out_sig_bt[total_c_args++] = T_VOID;
  11.110 +    } else if ( bt == T_FLOAT) {
  11.111 +      // We convert float to int
  11.112 +      out_sig_bt[total_c_args-1] = T_INT;
  11.113 +    }
  11.114 +  }
  11.115 +
  11.116 +  assert(i==total_args_passed, "validly parsed signature");
  11.117 +
  11.118 +  // Now get the compiled-Java layout as input arguments
  11.119 +  int comp_args_on_stack;
  11.120 +  comp_args_on_stack = SharedRuntime::java_calling_convention(
  11.121 +      in_sig_bt, in_regs, total_args_passed, false);
  11.122 +
  11.123 +  // Now figure out where the args must be stored and how much stack space
  11.124 +  // they require (neglecting out_preserve_stack_slots but space for storing
  11.125 +  // the 1st six register arguments). It's weird see int_stk_helper.
  11.126 +
  11.127 +  int out_arg_slots;
  11.128 +  out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args);
  11.129 +
  11.130 +  // Calculate the total number of stack slots we will need.
  11.131 +
  11.132 +  // First count the abi requirement plus all of the outgoing args
  11.133 +  int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
  11.134 +
  11.135 +  // Now space for the string(s) we must convert
  11.136 +  int* string_locs   = NEW_RESOURCE_ARRAY(int, total_strings + 1);
  11.137 +  for (i = 0; i < total_strings ; i++) {
  11.138 +    string_locs[i] = stack_slots;
  11.139 +    stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size;
  11.140 +  }
  11.141 +
  11.142 +  // Plus the temps we might need to juggle register args
  11.143 +  // regs take two slots each
  11.144 +  stack_slots += (Argument::n_int_register_parameters_c +
  11.145 +                  Argument::n_float_register_parameters_c) * 2;
  11.146 +
  11.147 +
  11.148 +  // + 4 for return address (which we own) and saved rbp,
  11.149 +
  11.150 +  stack_slots += 4;
  11.151 +
  11.152 +  // Ok The space we have allocated will look like:
  11.153 +  //
  11.154 +  //
  11.155 +  // FP-> |                     |
  11.156 +  //      |---------------------|
  11.157 +  //      | string[n]           |
  11.158 +  //      |---------------------| <- string_locs[n]
  11.159 +  //      | string[n-1]         |
  11.160 +  //      |---------------------| <- string_locs[n-1]
  11.161 +  //      | ...                 |
  11.162 +  //      | ...                 |
  11.163 +  //      |---------------------| <- string_locs[1]
  11.164 +  //      | string[0]           |
  11.165 +  //      |---------------------| <- string_locs[0]
  11.166 +  //      | outbound memory     |
  11.167 +  //      | based arguments     |
  11.168 +  //      |                     |
  11.169 +  //      |---------------------|
  11.170 +  //      |                     |
  11.171 +  // SP-> | out_preserved_slots |
  11.172 +  //
  11.173 +  //
  11.174 +
  11.175 +  // Now compute actual number of stack words we need rounding to make
  11.176 +  // stack properly aligned.
  11.177 +  stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word);
  11.178 +
  11.179 +  int stack_size = stack_slots * VMRegImpl::stack_slot_size;
  11.180 +
  11.181 +  intptr_t start = (intptr_t)__ pc();
  11.182 +
  11.183 +  // First thing make an ic check to see if we should even be here
  11.184 +
  11.185 +  // We are free to use all registers as temps without saving them and
  11.186 +  // restoring them except rbp. rbp, is the only callee save register
  11.187 +  // as far as the interpreter and the compiler(s) are concerned.
  11.188 +
  11.189 +  const Register ic_reg = rax;
  11.190 +  const Register receiver = rcx;
  11.191 +  Label hit;
  11.192 +  Label exception_pending;
  11.193 +
  11.194 +
  11.195 +  __ verify_oop(receiver);
  11.196 +  __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
  11.197 +  __ jcc(Assembler::equal, hit);
  11.198 +
  11.199 +  __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
  11.200 +
  11.201 +  // verified entry must be aligned for code patching.
  11.202 +  // and the first 5 bytes must be in the same cache line
  11.203 +  // if we align at 8 then we will be sure 5 bytes are in the same line
  11.204 +  __ align(8);
  11.205 +
  11.206 +  __ bind(hit);
  11.207 +
  11.208 +  int vep_offset = ((intptr_t)__ pc()) - start;
  11.209 +
  11.210 +
  11.211 +  // The instruction at the verified entry point must be 5 bytes or longer
  11.212 +  // because it can be patched on the fly by make_non_entrant. The stack bang
  11.213 +  // instruction fits that requirement.
  11.214 +
  11.215 +  // Generate stack overflow check
  11.216 +
  11.217 +  if (UseStackBanging) {
  11.218 +    if (stack_size <= StackShadowPages*os::vm_page_size()) {
  11.219 +      __ bang_stack_with_offset(StackShadowPages*os::vm_page_size());
  11.220 +    } else {
  11.221 +      __ movl(rax, stack_size);
  11.222 +      __ bang_stack_size(rax, rbx);
  11.223 +    }
  11.224 +  } else {
  11.225 +    // need a 5 byte instruction to allow MT safe patching to non-entrant
  11.226 +    __ fat_nop();
  11.227 +  }
  11.228 +
  11.229 +  assert(((uintptr_t)__ pc() - start - vep_offset) >= 5,
  11.230 +         "valid size for make_non_entrant");
  11.231 +
  11.232 +  // Generate a new frame for the wrapper.
  11.233 +  __ enter();
  11.234 +
  11.235 +  // -4 because return address is already present and so is saved rbp,
  11.236 +  if (stack_size - 2*wordSize != 0) {
  11.237 +    __ subq(rsp, stack_size - 2*wordSize);
  11.238 +  }
  11.239 +
  11.240 +  // Frame is now completed as far a size and linkage.
  11.241 +
  11.242 +  int frame_complete = ((intptr_t)__ pc()) - start;
  11.243 +
  11.244 +  int c_arg, j_arg;
  11.245 +
  11.246 +  // State of input register args
  11.247 +
  11.248 +  bool  live[ConcreteRegisterImpl::number_of_registers];
  11.249 +
  11.250 +  live[j_rarg0->as_VMReg()->value()] = false;
  11.251 +  live[j_rarg1->as_VMReg()->value()] = false;
  11.252 +  live[j_rarg2->as_VMReg()->value()] = false;
  11.253 +  live[j_rarg3->as_VMReg()->value()] = false;
  11.254 +  live[j_rarg4->as_VMReg()->value()] = false;
  11.255 +  live[j_rarg5->as_VMReg()->value()] = false;
  11.256 +
  11.257 +  live[j_farg0->as_VMReg()->value()] = false;
  11.258 +  live[j_farg1->as_VMReg()->value()] = false;
  11.259 +  live[j_farg2->as_VMReg()->value()] = false;
  11.260 +  live[j_farg3->as_VMReg()->value()] = false;
  11.261 +  live[j_farg4->as_VMReg()->value()] = false;
  11.262 +  live[j_farg5->as_VMReg()->value()] = false;
  11.263 +  live[j_farg6->as_VMReg()->value()] = false;
  11.264 +  live[j_farg7->as_VMReg()->value()] = false;
  11.265 +
  11.266 +
  11.267 +  bool rax_is_zero = false;
  11.268 +
  11.269 +  // All args (except strings) destined for the stack are moved first
  11.270 +  for (j_arg = first_arg_to_pass, c_arg = 0 ;
  11.271 +       j_arg < total_args_passed ; j_arg++, c_arg++ ) {
  11.272 +    VMRegPair src = in_regs[j_arg];
  11.273 +    VMRegPair dst = out_regs[c_arg];
  11.274 +
  11.275 +    // Get the real reg value or a dummy (rsp)
  11.276 +
  11.277 +    int src_reg = src.first()->is_reg() ?
  11.278 +                  src.first()->value() :
  11.279 +                  rsp->as_VMReg()->value();
  11.280 +
  11.281 +    bool useless =  in_sig_bt[j_arg] == T_ARRAY ||
  11.282 +                    (in_sig_bt[j_arg] == T_OBJECT &&
  11.283 +                     out_sig_bt[c_arg] != T_INT &&
  11.284 +                     out_sig_bt[c_arg] != T_ADDRESS &&
  11.285 +                     out_sig_bt[c_arg] != T_LONG);
  11.286 +
  11.287 +    live[src_reg] = !useless;
  11.288 +
  11.289 +    if (dst.first()->is_stack()) {
  11.290 +
  11.291 +      // Even though a string arg in a register is still live after this loop
  11.292 +      // after the string conversion loop (next) it will be dead so we take
  11.293 +      // advantage of that now for simpler code to manage live.
  11.294 +
  11.295 +      live[src_reg] = false;
  11.296 +      switch (in_sig_bt[j_arg]) {
  11.297 +
  11.298 +        case T_ARRAY:
  11.299 +        case T_OBJECT:
  11.300 +          {
  11.301 +            Address stack_dst(rsp, reg2offset_out(dst.first()));
  11.302 +
  11.303 +            if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) {
  11.304 +              // need to unbox a one-word value
  11.305 +              Register in_reg = rax;
  11.306 +              if ( src.first()->is_reg() ) {
  11.307 +                in_reg = src.first()->as_Register();
  11.308 +              } else {
  11.309 +                __ movq(rax, Address(rbp, reg2offset_in(src.first())));
  11.310 +                rax_is_zero = false;
  11.311 +              }
  11.312 +              Label skipUnbox;
  11.313 +              __ movptr(Address(rsp, reg2offset_out(dst.first())),
  11.314 +                        (int32_t)NULL_WORD);
  11.315 +              __ testq(in_reg, in_reg);
  11.316 +              __ jcc(Assembler::zero, skipUnbox);
  11.317 +
  11.318 +              Address src1(in_reg, box_offset);
  11.319 +              if ( out_sig_bt[c_arg] == T_LONG ) {
  11.320 +                __ movq(in_reg,  src1);
  11.321 +                __ movq(stack_dst, in_reg);
  11.322 +                assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  11.323 +                ++c_arg; // skip over T_VOID to keep the loop indices in sync
  11.324 +              } else {
  11.325 +                __ movl(in_reg,  src1);
  11.326 +                __ movl(stack_dst, in_reg);
  11.327 +              }
  11.328 +
  11.329 +              __ bind(skipUnbox);
  11.330 +            } else if (out_sig_bt[c_arg] != T_ADDRESS) {
  11.331 +              // Convert the arg to NULL
  11.332 +              if (!rax_is_zero) {
  11.333 +                __ xorq(rax, rax);
  11.334 +                rax_is_zero = true;
  11.335 +              }
  11.336 +              __ movq(stack_dst, rax);
  11.337 +            }
  11.338 +          }
  11.339 +          break;
  11.340 +
  11.341 +        case T_VOID:
  11.342 +          break;
  11.343 +
  11.344 +        case T_FLOAT:
  11.345 +          // This does the right thing since we know it is destined for the
  11.346 +          // stack
  11.347 +          float_move(masm, src, dst);
  11.348 +          break;
  11.349 +
  11.350 +        case T_DOUBLE:
  11.351 +          // This does the right thing since we know it is destined for the
  11.352 +          // stack
  11.353 +          double_move(masm, src, dst);
  11.354 +          break;
  11.355 +
  11.356 +        case T_LONG :
  11.357 +          long_move(masm, src, dst);
  11.358 +          break;
  11.359 +
  11.360 +        case T_ADDRESS: assert(false, "found T_ADDRESS in java args");
  11.361 +
  11.362 +        default:
  11.363 +          move32_64(masm, src, dst);
  11.364 +      }
  11.365 +    }
  11.366 +
  11.367 +  }
  11.368 +
  11.369 +  // If we have any strings we must store any register based arg to the stack
  11.370 +  // This includes any still live xmm registers too.
  11.371 +
  11.372 +  int sid = 0;
  11.373 +
  11.374 +  if (total_strings > 0 ) {
  11.375 +    for (j_arg = first_arg_to_pass, c_arg = 0 ;
  11.376 +         j_arg < total_args_passed ; j_arg++, c_arg++ ) {
  11.377 +      VMRegPair src = in_regs[j_arg];
  11.378 +      VMRegPair dst = out_regs[c_arg];
  11.379 +
  11.380 +      if (src.first()->is_reg()) {
  11.381 +        Address src_tmp(rbp, fp_offset[src.first()->value()]);
  11.382 +
  11.383 +        // string oops were left untouched by the previous loop even if the
  11.384 +        // eventual (converted) arg is destined for the stack so park them
  11.385 +        // away now (except for first)
  11.386 +
  11.387 +        if (out_sig_bt[c_arg] == T_ADDRESS) {
  11.388 +          Address utf8_addr = Address(
  11.389 +              rsp, string_locs[sid++] * VMRegImpl::stack_slot_size);
  11.390 +          if (sid != 1) {
  11.391 +            // The first string arg won't be killed until after the utf8
  11.392 +            // conversion
  11.393 +            __ movq(utf8_addr, src.first()->as_Register());
  11.394 +          }
  11.395 +        } else if (dst.first()->is_reg()) {
  11.396 +          if (in_sig_bt[j_arg] == T_FLOAT || in_sig_bt[j_arg] == T_DOUBLE) {
  11.397 +
  11.398 +            // Convert the xmm register to an int and store it in the reserved
  11.399 +            // location for the eventual c register arg
  11.400 +            XMMRegister f = src.first()->as_XMMRegister();
  11.401 +            if (in_sig_bt[j_arg] == T_FLOAT) {
  11.402 +              __ movflt(src_tmp, f);
  11.403 +            } else {
  11.404 +              __ movdbl(src_tmp, f);
  11.405 +            }
  11.406 +          } else {
  11.407 +            // If the arg is an oop type we don't support don't bother to store
  11.408 +            // it remember string was handled above.
  11.409 +            bool useless =  in_sig_bt[j_arg] == T_ARRAY ||
  11.410 +                            (in_sig_bt[j_arg] == T_OBJECT &&
  11.411 +                             out_sig_bt[c_arg] != T_INT &&
  11.412 +                             out_sig_bt[c_arg] != T_LONG);
  11.413 +
  11.414 +            if (!useless) {
  11.415 +              __ movq(src_tmp, src.first()->as_Register());
  11.416 +            }
  11.417 +          }
  11.418 +        }
  11.419 +      }
  11.420 +      if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) {
  11.421 +        assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  11.422 +        ++c_arg; // skip over T_VOID to keep the loop indices in sync
  11.423 +      }
  11.424 +    }
  11.425 +
  11.426 +    // Now that the volatile registers are safe, convert all the strings
  11.427 +    sid = 0;
  11.428 +
  11.429 +    for (j_arg = first_arg_to_pass, c_arg = 0 ;
  11.430 +         j_arg < total_args_passed ; j_arg++, c_arg++ ) {
  11.431 +      if (out_sig_bt[c_arg] == T_ADDRESS) {
  11.432 +        // It's a string
  11.433 +        Address utf8_addr = Address(
  11.434 +            rsp, string_locs[sid++] * VMRegImpl::stack_slot_size);
  11.435 +        // The first string we find might still be in the original java arg
  11.436 +        // register
  11.437 +
  11.438 +        VMReg src = in_regs[j_arg].first();
  11.439 +
  11.440 +        // We will need to eventually save the final argument to the trap
  11.441 +        // in the von-volatile location dedicated to src. This is the offset
  11.442 +        // from fp we will use.
  11.443 +        int src_off = src->is_reg() ?
  11.444 +            fp_offset[src->value()] : reg2offset_in(src);
  11.445 +
  11.446 +        // This is where the argument will eventually reside
  11.447 +        VMRegPair dst = out_regs[c_arg];
  11.448 +
  11.449 +        if (src->is_reg()) {
  11.450 +          if (sid == 1) {
  11.451 +            __ movq(c_rarg0, src->as_Register());
  11.452 +          } else {
  11.453 +            __ movq(c_rarg0, utf8_addr);
  11.454 +          }
  11.455 +        } else {
  11.456 +          // arg is still in the original location
  11.457 +          __ movq(c_rarg0, Address(rbp, reg2offset_in(src)));
  11.458 +        }
  11.459 +        Label done, convert;
  11.460 +
  11.461 +        // see if the oop is NULL
  11.462 +        __ testq(c_rarg0, c_rarg0);
  11.463 +        __ jcc(Assembler::notEqual, convert);
  11.464 +
  11.465 +        if (dst.first()->is_reg()) {
  11.466 +          // Save the ptr to utf string in the origina src loc or the tmp
  11.467 +          // dedicated to it
  11.468 +          __ movq(Address(rbp, src_off), c_rarg0);
  11.469 +        } else {
  11.470 +          __ movq(Address(rsp, reg2offset_out(dst.first())), c_rarg0);
  11.471 +        }
  11.472 +        __ jmp(done);
  11.473 +
  11.474 +        __ bind(convert);
  11.475 +
  11.476 +        __ lea(c_rarg1, utf8_addr);
  11.477 +        if (dst.first()->is_reg()) {
  11.478 +          __ movq(Address(rbp, src_off), c_rarg1);
  11.479 +        } else {
  11.480 +          __ movq(Address(rsp, reg2offset_out(dst.first())), c_rarg1);
  11.481 +        }
  11.482 +        // And do the conversion
  11.483 +        __ call(RuntimeAddress(
  11.484 +                CAST_FROM_FN_PTR(address, SharedRuntime::get_utf)));
  11.485 +
  11.486 +        __ bind(done);
  11.487 +      }
  11.488 +      if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) {
  11.489 +        assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  11.490 +        ++c_arg; // skip over T_VOID to keep the loop indices in sync
  11.491 +      }
  11.492 +    }
  11.493 +    // The get_utf call killed all the c_arg registers
  11.494 +    live[c_rarg0->as_VMReg()->value()] = false;
  11.495 +    live[c_rarg1->as_VMReg()->value()] = false;
  11.496 +    live[c_rarg2->as_VMReg()->value()] = false;
  11.497 +    live[c_rarg3->as_VMReg()->value()] = false;
  11.498 +    live[c_rarg4->as_VMReg()->value()] = false;
  11.499 +    live[c_rarg5->as_VMReg()->value()] = false;
  11.500 +
  11.501 +    live[c_farg0->as_VMReg()->value()] = false;
  11.502 +    live[c_farg1->as_VMReg()->value()] = false;
  11.503 +    live[c_farg2->as_VMReg()->value()] = false;
  11.504 +    live[c_farg3->as_VMReg()->value()] = false;
  11.505 +    live[c_farg4->as_VMReg()->value()] = false;
  11.506 +    live[c_farg5->as_VMReg()->value()] = false;
  11.507 +    live[c_farg6->as_VMReg()->value()] = false;
  11.508 +    live[c_farg7->as_VMReg()->value()] = false;
  11.509 +  }
  11.510 +
  11.511 +  // Now we can finally move the register args to their desired locations
  11.512 +
  11.513 +  rax_is_zero = false;
  11.514 +
  11.515 +  for (j_arg = first_arg_to_pass, c_arg = 0 ;
  11.516 +       j_arg < total_args_passed ; j_arg++, c_arg++ ) {
  11.517 +
  11.518 +    VMRegPair src = in_regs[j_arg];
  11.519 +    VMRegPair dst = out_regs[c_arg];
  11.520 +
  11.521 +    // Only need to look for args destined for the interger registers (since we
  11.522 +    // convert float/double args to look like int/long outbound)
  11.523 +    if (dst.first()->is_reg()) {
  11.524 +      Register r =  dst.first()->as_Register();
  11.525 +
  11.526 +      // Check if the java arg is unsupported and thereofre useless
  11.527 +      bool useless =  in_sig_bt[j_arg] == T_ARRAY ||
  11.528 +                      (in_sig_bt[j_arg] == T_OBJECT &&
  11.529 +                       out_sig_bt[c_arg] != T_INT &&
  11.530 +                       out_sig_bt[c_arg] != T_ADDRESS &&
  11.531 +                       out_sig_bt[c_arg] != T_LONG);
  11.532 +
  11.533 +
  11.534 +      // If we're going to kill an existing arg save it first
  11.535 +      if (live[dst.first()->value()]) {
  11.536 +        // you can't kill yourself
  11.537 +        if (src.first() != dst.first()) {
  11.538 +          __ movq(Address(rbp, fp_offset[dst.first()->value()]), r);
  11.539 +        }
  11.540 +      }
  11.541 +      if (src.first()->is_reg()) {
  11.542 +        if (live[src.first()->value()] ) {
  11.543 +          if (in_sig_bt[j_arg] == T_FLOAT) {
  11.544 +            __ movdl(r, src.first()->as_XMMRegister());
  11.545 +          } else if (in_sig_bt[j_arg] == T_DOUBLE) {
  11.546 +            __ movdq(r, src.first()->as_XMMRegister());
  11.547 +          } else if (r != src.first()->as_Register()) {
  11.548 +            if (!useless) {
  11.549 +              __ movq(r, src.first()->as_Register());
  11.550 +            }
  11.551 +          }
  11.552 +        } else {
  11.553 +          // If the arg is an oop type we don't support don't bother to store
  11.554 +          // it
  11.555 +          if (!useless) {
  11.556 +            if (in_sig_bt[j_arg] == T_DOUBLE ||
  11.557 +                in_sig_bt[j_arg] == T_LONG  ||
  11.558 +                in_sig_bt[j_arg] == T_OBJECT ) {
  11.559 +              __ movq(r, Address(rbp, fp_offset[src.first()->value()]));
  11.560 +            } else {
  11.561 +              __ movl(r, Address(rbp, fp_offset[src.first()->value()]));
  11.562 +            }
  11.563 +          }
  11.564 +        }
  11.565 +        live[src.first()->value()] = false;
  11.566 +      } else if (!useless) {
  11.567 +        // full sized move even for int should be ok
  11.568 +        __ movq(r, Address(rbp, reg2offset_in(src.first())));
  11.569 +      }
  11.570 +
  11.571 +      // At this point r has the original java arg in the final location
  11.572 +      // (assuming it wasn't useless). If the java arg was an oop
  11.573 +      // we have a bit more to do
  11.574 +
  11.575 +      if (in_sig_bt[j_arg] == T_ARRAY || in_sig_bt[j_arg] == T_OBJECT ) {
  11.576 +        if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) {
  11.577 +          // need to unbox a one-word value
  11.578 +          Label skip;
  11.579 +          __ testq(r, r);
  11.580 +          __ jcc(Assembler::equal, skip);
  11.581 +          Address src1(r, box_offset);
  11.582 +          if ( out_sig_bt[c_arg] == T_LONG ) {
  11.583 +            __ movq(r, src1);
  11.584 +          } else {
  11.585 +            __ movl(r, src1);
  11.586 +          }
  11.587 +          __ bind(skip);
  11.588 +
  11.589 +        } else if (out_sig_bt[c_arg] != T_ADDRESS) {
  11.590 +          // Convert the arg to NULL
  11.591 +          __ xorq(r, r);
  11.592 +        }
  11.593 +      }
  11.594 +
  11.595 +      // dst can longer be holding an input value
  11.596 +      live[dst.first()->value()] = false;
  11.597 +    }
  11.598 +    if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) {
  11.599 +      assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
  11.600 +      ++c_arg; // skip over T_VOID to keep the loop indices in sync
  11.601 +    }
  11.602 +  }
  11.603 +
  11.604 +
  11.605 +  // Ok now we are done. Need to place the nop that dtrace wants in order to
  11.606 +  // patch in the trap
  11.607 +  int patch_offset = ((intptr_t)__ pc()) - start;
  11.608 +
  11.609 +  __ nop();
  11.610 +
  11.611 +
  11.612 +  // Return
  11.613 +
  11.614 +  __ leave();
  11.615 +  __ ret(0);
  11.616 +
  11.617 +  __ flush();
  11.618 +
  11.619 +  nmethod *nm = nmethod::new_dtrace_nmethod(
  11.620 +      method, masm->code(), vep_offset, patch_offset, frame_complete,
  11.621 +      stack_slots / VMRegImpl::slots_per_word);
  11.622 +  return nm;
  11.623 +
  11.624 +}
  11.625 +
  11.626 +#endif // HAVE_DTRACE_H
  11.627 +
  11.628  // this function returns the adjust size (in number of words) to a c2i adapter
  11.629  // activation for use during deoptimization
  11.630  int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) {
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/os/linux/vm/dtraceJSDT_linux.cpp	Thu Apr 17 22:18:15 2008 -0400
    12.3 @@ -0,0 +1,39 @@
    12.4 +/*
    12.5 + * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.
   12.11 + *
   12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.15 + * version 2 for more details (a copy is included in the LICENSE file that
   12.16 + * accompanied this code).
   12.17 + *
   12.18 + * You should have received a copy of the GNU General Public License version
   12.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.21 + *
   12.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   12.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   12.24 + * have any questions.
   12.25 + *
   12.26 + */
   12.27 +
   12.28 +#include "incls/_precompiled.incl"
   12.29 +#include "incls/_dtraceJSDT_linux.cpp.incl"
   12.30 +
   12.31 +int DTraceJSDT::pd_activate(
   12.32 +    void* baseAddress, jstring module,
   12.33 +    jint providers_count, JVM_DTraceProvider* providers) {
   12.34 +  return -1;
   12.35 +}
   12.36 +
   12.37 +void DTraceJSDT::pd_dispose(int handle) {
   12.38 +}
   12.39 +
   12.40 +jboolean DTraceJSDT::pd_is_supported() {
   12.41 +  return false;
   12.42 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/os/solaris/vm/dtraceJSDT_solaris.cpp	Thu Apr 17 22:18:15 2008 -0400
    13.3 @@ -0,0 +1,685 @@
    13.4 +/*
    13.5 + * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + *
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + *
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + *
   13.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   13.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   13.24 + * have any questions.
   13.25 + *
   13.26 + */
   13.27 +
   13.28 +#include "incls/_precompiled.incl"
   13.29 +#include "incls/_dtraceJSDT_solaris.cpp.incl"
   13.30 +
   13.31 +#ifdef HAVE_DTRACE_H
   13.32 +
   13.33 +#include <sys/types.h>
   13.34 +#include <sys/stat.h>
   13.35 +#include <fcntl.h>
   13.36 +#include <unistd.h>
   13.37 +#include <dtrace.h>
   13.38 +
   13.39 +static const char* devname    = "/dev/dtrace/helper";
   13.40 +static const char* olddevname = "/devices/pseudo/dtrace@0:helper";
   13.41 +
   13.42 +static const char* string_sig = "uintptr_t";
   13.43 +static const char* int_sig    = "long";
   13.44 +static const char* long_sig   = "long long";
   13.45 +
   13.46 +static void printDOFHelper(dof_helper_t* helper);
   13.47 +
   13.48 +static int dofhelper_open() {
   13.49 +  int fd;
   13.50 +  if ((fd = open64(devname, O_RDWR)) < 0) {
   13.51 +    // Optimize next calls
   13.52 +    devname = olddevname;
   13.53 +    if ((fd = open64(devname, O_RDWR)) < 0) {
   13.54 +      return -1;
   13.55 +    }
   13.56 +  }
   13.57 +  return fd;
   13.58 +}
   13.59 +
   13.60 +static jint dof_register(jstring module, uint8_t* dof, void* modaddr) {
   13.61 +  int probe;
   13.62 +  dof_helper_t dh;
   13.63 +  int fd;
   13.64 +
   13.65 +  memset(&dh, 0, sizeof(dh));
   13.66 +
   13.67 +  char* module_name = java_lang_String::as_utf8_string(
   13.68 +        JNIHandles::resolve_non_null(module));
   13.69 +  jio_snprintf(dh.dofhp_mod, sizeof(dh.dofhp_mod), "%s", module_name);
   13.70 +  dh.dofhp_dof  = (uint64_t)dof;
   13.71 +  dh.dofhp_addr = (uint64_t)modaddr;
   13.72 +
   13.73 +  fd = dofhelper_open();
   13.74 +  if (fd < 0)
   13.75 +    return -1;
   13.76 +  probe = ioctl(fd, DTRACEHIOC_ADDDOF, &dh);
   13.77 +  close(fd);
   13.78 +  if (PrintDTraceDOF) {
   13.79 +    printDOFHelper(&dh);
   13.80 +    tty->print_cr("DOF helper id = %d", probe);
   13.81 +  }
   13.82 +  return probe;
   13.83 +}
   13.84 +
   13.85 +int DTraceJSDT::pd_activate(
   13.86 +    void* moduleBaseAddress, jstring module,
   13.87 +    jint providers_count, JVM_DTraceProvider* providers) {
   13.88 +
   13.89 +  // We need sections:
   13.90 +  //  (1) STRTAB
   13.91 +  //  (
   13.92 +  //    (2) PROVIDER
   13.93 +  //    (3) PROBES
   13.94 +  //    (4) PROBOFFS
   13.95 +  //    (5) PROBARGS
   13.96 +  //  ) * Number of Providers
   13.97 +
   13.98 +  // Type of sections we create
   13.99 +  enum {
  13.100 +    STRTAB = 0,
  13.101 +    PROVIDERS = 1,
  13.102 +    PROBES = 2,
  13.103 +    PROBE_OFFSETS = 3,
  13.104 +    ARG_OFFSETS = 4,
  13.105 +    NUM_SECTIONS = 5
  13.106 +  };
  13.107 +
  13.108 +  static int alignment_for[NUM_SECTIONS] = { 1, 4, 8, 4, 1 };
  13.109 +
  13.110 +  ResourceMark rm;
  13.111 +
  13.112 +  uint32_t num_sections = 1 + 4 * providers_count;
  13.113 +  uint32_t offset = sizeof(dof_hdr_t) + (num_sections * sizeof(dof_sec_t));
  13.114 +  uint32_t* secoffs = NEW_RESOURCE_ARRAY(uint32_t, num_sections);
  13.115 +  uint32_t* secsize = NEW_RESOURCE_ARRAY(uint32_t, num_sections);
  13.116 +
  13.117 +  // Store offsets of all strings here in such order:
  13.118 +  //  zero-string (always 0)
  13.119 +  //  provider1-name
  13.120 +  //    probe1-function
  13.121 +  //    probe1-name
  13.122 +  //    arg-1
  13.123 +  //    arg-2
  13.124 +  //    ...
  13.125 +  //    probe2-function
  13.126 +  //    probe2-name
  13.127 +  //    arg-1
  13.128 +  //    arg-2
  13.129 +  //  provider2-name
  13.130 +  //    ...
  13.131 +
  13.132 +  uint32_t strcount  = 0;
  13.133 +  // Count the number of strings we'll need
  13.134 +  for(int prvc = 0; prvc < providers_count; ++prvc) {
  13.135 +    JVM_DTraceProvider* provider = &providers[prvc];
  13.136 +    // Provider name
  13.137 +    ++strcount;
  13.138 +    for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.139 +      JVM_DTraceProbe* p = &(provider->probes[prbc]);
  13.140 +      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
  13.141 +      // function + name + one per argument
  13.142 +      strcount += 2 + ArgumentCount(sig).size();
  13.143 +    }
  13.144 +  }
  13.145 +
  13.146 +  // Create place for string offsets
  13.147 +  uint32_t* stroffs = NEW_RESOURCE_ARRAY(uint32_t, strcount + 1);
  13.148 +  uint32_t string_index = 0;
  13.149 +  uint32_t curstr = 0;
  13.150 +
  13.151 +  // First we need an empty string: ""
  13.152 +  stroffs[curstr++] = string_index;
  13.153 +  string_index += strlen("") + 1;
  13.154 +
  13.155 +  for(int prvc = 0; prvc < providers_count; ++prvc) {
  13.156 +    JVM_DTraceProvider* provider = &providers[prvc];
  13.157 +    char* provider_name = java_lang_String::as_utf8_string(
  13.158 +        JNIHandles::resolve_non_null(provider->name));
  13.159 +    stroffs[curstr++] = string_index;
  13.160 +    string_index += strlen(provider_name) + 1;
  13.161 +
  13.162 +    // All probes
  13.163 +    for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.164 +      JVM_DTraceProbe* p = &(provider->probes[prbc]);
  13.165 +
  13.166 +      char* function = java_lang_String::as_utf8_string(
  13.167 +          JNIHandles::resolve_non_null(p->function));
  13.168 +      stroffs[curstr++] = string_index;
  13.169 +      string_index += strlen(function) + 1;
  13.170 +
  13.171 +      char* name = java_lang_String::as_utf8_string(
  13.172 +          JNIHandles::resolve_non_null(p->name));
  13.173 +      stroffs[curstr++] = string_index;
  13.174 +      string_index += strlen(name) + 1;
  13.175 +
  13.176 +      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
  13.177 +      SignatureStream ss(sig);
  13.178 +      for ( ; !ss.at_return_type(); ss.next()) {
  13.179 +        BasicType bt = ss.type();
  13.180 +        const char* t = NULL;
  13.181 +        if (bt == T_OBJECT &&
  13.182 +            ss.as_symbol_or_null() == vmSymbols::java_lang_String()) {
  13.183 +          t = string_sig;
  13.184 +        } else if (bt == T_LONG) {
  13.185 +          t = long_sig;
  13.186 +        } else {
  13.187 +          t = int_sig;
  13.188 +        }
  13.189 +        stroffs[curstr++] = string_index;
  13.190 +        string_index += strlen(t) + 1;
  13.191 +      }
  13.192 +    }
  13.193 +  }
  13.194 +  secoffs[STRTAB] = offset;
  13.195 +  secsize[STRTAB] = string_index;
  13.196 +  offset += string_index;
  13.197 +
  13.198 +  // Calculate the size of the rest
  13.199 +  for(int prvc = 0; prvc < providers_count; ++prvc) {
  13.200 +    JVM_DTraceProvider* provider = &providers[prvc];
  13.201 +    size_t provider_sec  = PROVIDERS     + prvc * 4;
  13.202 +    size_t probe_sec     = PROBES        + prvc * 4;
  13.203 +    size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4;
  13.204 +    size_t argoffs_sec   = ARG_OFFSETS   + prvc * 4;
  13.205 +
  13.206 +    // Allocate space for the provider data struction
  13.207 +    secoffs[provider_sec] = align_size_up(offset, alignment_for[PROVIDERS]);
  13.208 +    secsize[provider_sec] = sizeof(dof_provider_t);
  13.209 +    offset = secoffs[provider_sec] + secsize[provider_sec];
  13.210 +
  13.211 +    // Allocate space for all the probes
  13.212 +    secoffs[probe_sec] = align_size_up(offset, alignment_for[PROBES]);
  13.213 +    secsize[probe_sec] = sizeof(dof_probe_t) * provider->probe_count;
  13.214 +    offset = secoffs[probe_sec] + secsize[probe_sec];
  13.215 +
  13.216 +    // Allocate space for the probe offsets
  13.217 +    secoffs[probeoffs_sec] = align_size_up(offset, alignment_for[PROBE_OFFSETS]);
  13.218 +    secsize[probeoffs_sec] = sizeof(uint32_t) * provider->probe_count;
  13.219 +    offset = secoffs[probeoffs_sec] + secsize[probeoffs_sec];
  13.220 +
  13.221 +    // We need number of arguments argoffs
  13.222 +    uint32_t argscount = 0;
  13.223 +    for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.224 +       JVM_DTraceProbe* p = &(provider->probes[prbc]);
  13.225 +       symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
  13.226 +       argscount += ArgumentCount(sig).size();
  13.227 +    }
  13.228 +    secoffs[argoffs_sec] = align_size_up(offset, alignment_for[ARG_OFFSETS]);
  13.229 +    secsize[argoffs_sec] = sizeof(uint8_t) * argscount;
  13.230 +    offset = secoffs[argoffs_sec] + secsize[argoffs_sec];
  13.231 +  }
  13.232 +
  13.233 +  uint32_t size = offset;
  13.234 +
  13.235 +  uint8_t* dof = NEW_RESOURCE_ARRAY(uint8_t, size);
  13.236 +  if (!dof) {
  13.237 +    return -1;
  13.238 +  }
  13.239 +  memset((void*)dof, 0, size);
  13.240 +
  13.241 +  // Fill memory with proper values
  13.242 +  dof_hdr_t* hdr = (dof_hdr_t*)dof;
  13.243 +  hdr->dofh_ident[DOF_ID_MAG0]     = DOF_MAG_MAG0;
  13.244 +  hdr->dofh_ident[DOF_ID_MAG1]     = DOF_MAG_MAG1;
  13.245 +  hdr->dofh_ident[DOF_ID_MAG2]     = DOF_MAG_MAG2;
  13.246 +  hdr->dofh_ident[DOF_ID_MAG3]     = DOF_MAG_MAG3;
  13.247 +  hdr->dofh_ident[DOF_ID_MODEL]    = DOF_MODEL_NATIVE;  // No variants
  13.248 +  hdr->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; // No variants
  13.249 +  hdr->dofh_ident[DOF_ID_VERSION]  = DOF_VERSION_1;     // No variants
  13.250 +  hdr->dofh_ident[DOF_ID_DIFVERS]  = DIF_VERSION_2;     // No variants
  13.251 +  // all other fields of ident to zero
  13.252 +
  13.253 +  hdr->dofh_flags   = 0;
  13.254 +  hdr->dofh_hdrsize = sizeof(dof_hdr_t);
  13.255 +  hdr->dofh_secsize = sizeof(dof_sec_t);
  13.256 +  hdr->dofh_secnum  = num_sections;
  13.257 +  hdr->dofh_secoff  = sizeof(dof_hdr_t);
  13.258 +  hdr->dofh_loadsz  = size;
  13.259 +  hdr->dofh_filesz  = size;
  13.260 +
  13.261 +  // First section: STRTAB
  13.262 +  dof_sec_t* sec = (dof_sec_t*)(dof + sizeof(dof_hdr_t));
  13.263 +  sec->dofs_type    = DOF_SECT_STRTAB;
  13.264 +  sec->dofs_align   = alignment_for[STRTAB];
  13.265 +  sec->dofs_flags   = DOF_SECF_LOAD;
  13.266 +  sec->dofs_entsize = 0;
  13.267 +  sec->dofs_offset  = secoffs[STRTAB];
  13.268 +  sec->dofs_size    = secsize[STRTAB];
  13.269 +  // Make data for this section
  13.270 +  char* str = (char*)(dof + sec->dofs_offset);
  13.271 +
  13.272 +  *str = 0; str += 1; // ""
  13.273 +
  13.274 +  // Run through all strings again
  13.275 +  for(int prvc = 0; prvc < providers_count; ++prvc) {
  13.276 +    JVM_DTraceProvider* provider = &providers[prvc];
  13.277 +    char* provider_name = java_lang_String::as_utf8_string(
  13.278 +        JNIHandles::resolve_non_null(provider->name));
  13.279 +    strcpy(str, provider_name);
  13.280 +    str += strlen(provider_name) + 1;
  13.281 +
  13.282 +    // All probes
  13.283 +    for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.284 +      JVM_DTraceProbe* p = &(provider->probes[prbc]);
  13.285 +
  13.286 +      char* function = java_lang_String::as_utf8_string(
  13.287 +          JNIHandles::resolve_non_null(p->function));
  13.288 +      strcpy(str, function);
  13.289 +      str += strlen(str) + 1;
  13.290 +
  13.291 +      char* name = java_lang_String::as_utf8_string(
  13.292 +          JNIHandles::resolve_non_null(p->name));
  13.293 +      strcpy(str, name);
  13.294 +      str += strlen(name) + 1;
  13.295 +
  13.296 +      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
  13.297 +      SignatureStream ss(sig);
  13.298 +      for ( ; !ss.at_return_type(); ss.next()) {
  13.299 +        BasicType bt = ss.type();
  13.300 +        const char* t;
  13.301 +        if (bt == T_OBJECT &&
  13.302 +            ss.as_symbol_or_null() == vmSymbols::java_lang_String()) {
  13.303 +          t = string_sig;
  13.304 +        } else if (bt == T_LONG) {
  13.305 +          t = long_sig;
  13.306 +        } else {
  13.307 +          t = int_sig;
  13.308 +        }
  13.309 +        strcpy(str, t);
  13.310 +        str += strlen(t) + 1;
  13.311 +      }
  13.312 +    }
  13.313 +  }
  13.314 +
  13.315 +  curstr = 1;
  13.316 +  for(int prvc = 0; prvc < providers_count; ++prvc) {
  13.317 +    JVM_DTraceProvider* provider = &providers[prvc];
  13.318 +    size_t provider_sec  = PROVIDERS     + prvc * 4;
  13.319 +    size_t probe_sec     = PROBES        + prvc * 4;
  13.320 +    size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4;
  13.321 +    size_t argoffs_sec   = ARG_OFFSETS   + prvc * 4;
  13.322 +
  13.323 +    // PROVIDER ///////////////////////////////////////////////////////////////
  13.324 +    // Section header
  13.325 +    sec = (dof_sec_t*)
  13.326 +        (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * provider_sec);
  13.327 +    sec->dofs_type    = DOF_SECT_PROVIDER;
  13.328 +    sec->dofs_align   = alignment_for[PROVIDERS];
  13.329 +    sec->dofs_flags   = DOF_SECF_LOAD;
  13.330 +    sec->dofs_entsize = 0;
  13.331 +    sec->dofs_offset  = secoffs[provider_sec];
  13.332 +    sec->dofs_size    = secsize[provider_sec];
  13.333 +    // Make provider decriiption
  13.334 +    dof_provider_t* prv = (dof_provider_t*)(dof + sec->dofs_offset);
  13.335 +    prv->dofpv_strtab   = STRTAB;
  13.336 +    prv->dofpv_probes   = probe_sec;
  13.337 +    prv->dofpv_prargs   = argoffs_sec;
  13.338 +    prv->dofpv_proffs   = probeoffs_sec;
  13.339 +    prv->dofpv_name     = stroffs[curstr++]; // Index in string table
  13.340 +    prv->dofpv_provattr = DOF_ATTR(
  13.341 +        provider->providerAttributes.nameStability,
  13.342 +        provider->providerAttributes.dataStability,
  13.343 +        provider->providerAttributes.dependencyClass);
  13.344 +    prv->dofpv_modattr = DOF_ATTR(
  13.345 +        provider->moduleAttributes.nameStability,
  13.346 +        provider->moduleAttributes.dataStability,
  13.347 +        provider->moduleAttributes.dependencyClass);
  13.348 +    prv->dofpv_funcattr = DOF_ATTR(
  13.349 +        provider->functionAttributes.nameStability,
  13.350 +        provider->functionAttributes.dataStability,
  13.351 +        provider->functionAttributes.dependencyClass);
  13.352 +    prv->dofpv_nameattr = DOF_ATTR(
  13.353 +        provider->nameAttributes.nameStability,
  13.354 +        provider->nameAttributes.dataStability,
  13.355 +        provider->nameAttributes.dependencyClass);
  13.356 +    prv->dofpv_argsattr = DOF_ATTR(
  13.357 +        provider->argsAttributes.nameStability,
  13.358 +        provider->argsAttributes.dataStability,
  13.359 +        provider->argsAttributes.dependencyClass);
  13.360 +
  13.361 +    // PROBES /////////////////////////////////////////////////////////////////
  13.362 +    // Section header
  13.363 +    sec = (dof_sec_t*)
  13.364 +        (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probe_sec);
  13.365 +    sec->dofs_type    = DOF_SECT_PROBES;
  13.366 +    sec->dofs_align   = alignment_for[PROBES];
  13.367 +    sec->dofs_flags   = DOF_SECF_LOAD;
  13.368 +    sec->dofs_entsize = sizeof(dof_probe_t);
  13.369 +    sec->dofs_offset  = secoffs[probe_sec];
  13.370 +    sec->dofs_size    = secsize[probe_sec];
  13.371 +    // Make probes descriptions
  13.372 +    uint32_t argsoffs = 0;
  13.373 +    for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.374 +      JVM_DTraceProbe* probe = &(provider->probes[prbc]);
  13.375 +      methodOop m = JNIHandles::resolve_jmethod_id(probe->method);
  13.376 +      int arg_count = ArgumentCount(m->signature()).size();
  13.377 +      assert(m->code() != NULL, "must have an nmethod");
  13.378 +
  13.379 +      dof_probe_t* prb =
  13.380 +         (dof_probe_t*)(dof + sec->dofs_offset + prbc * sizeof(dof_probe_t));
  13.381 +
  13.382 +      prb->dofpr_addr   = (uint64_t)m->code()->entry_point();
  13.383 +      prb->dofpr_func   = stroffs[curstr++]; // Index in string table
  13.384 +      prb->dofpr_name   = stroffs[curstr++]; // Index in string table
  13.385 +      prb->dofpr_nargv  = stroffs[curstr  ]; // Index in string table
  13.386 +      // We spent siglen strings here
  13.387 +      curstr += arg_count;
  13.388 +      prb->dofpr_xargv  = prb->dofpr_nargv;  // Same bunch of strings
  13.389 +      prb->dofpr_argidx = argsoffs;
  13.390 +      prb->dofpr_offidx = prbc;
  13.391 +      prb->dofpr_nargc  = arg_count;
  13.392 +      prb->dofpr_xargc  = arg_count;
  13.393 +      prb->dofpr_noffs  = 1; // Number of offsets
  13.394 +      // Next bunch of offsets
  13.395 +      argsoffs += arg_count;
  13.396 +    }
  13.397 +
  13.398 +    // PROFFS /////////////////////////////////////////////////////////////////
  13.399 +    // Section header
  13.400 +    sec = (dof_sec_t*)
  13.401 +        (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probeoffs_sec);
  13.402 +    sec->dofs_type    = DOF_SECT_PROFFS;
  13.403 +    sec->dofs_align   = alignment_for[PROBE_OFFSETS];
  13.404 +    sec->dofs_flags   = DOF_SECF_LOAD;
  13.405 +    sec->dofs_entsize = sizeof(uint32_t);
  13.406 +    sec->dofs_offset  = secoffs[probeoffs_sec];
  13.407 +    sec->dofs_size    = secsize[probeoffs_sec];
  13.408 +    // Make offsets
  13.409 +    for (int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.410 +      uint32_t* pof =
  13.411 +          (uint32_t*)(dof + sec->dofs_offset + sizeof(uint32_t) * prbc);
  13.412 +      JVM_DTraceProbe* probe = &(provider->probes[prbc]);
  13.413 +      methodOop m = JNIHandles::resolve_jmethod_id(probe->method);
  13.414 +      *pof = m->code()->trap_offset();
  13.415 +    }
  13.416 +
  13.417 +    // PRARGS /////////////////////////////////////////////////////////////////
  13.418 +    // Section header
  13.419 +    sec = (dof_sec_t*)
  13.420 +        (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * argoffs_sec);
  13.421 +    sec->dofs_type    = DOF_SECT_PRARGS;
  13.422 +    sec->dofs_align   = alignment_for[ARG_OFFSETS];
  13.423 +    sec->dofs_flags   = DOF_SECF_LOAD;
  13.424 +    sec->dofs_entsize = sizeof(uint8_t);
  13.425 +    sec->dofs_offset  = secoffs[argoffs_sec];
  13.426 +    sec->dofs_size    = secsize[argoffs_sec];
  13.427 +    // Make arguments
  13.428 +    uint8_t* par = (uint8_t*)(dof + sec->dofs_offset);
  13.429 +    for (int prbc = 0; prbc < provider->probe_count; ++prbc) {
  13.430 +      JVM_DTraceProbe* p = &(provider->probes[prbc]);
  13.431 +      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
  13.432 +      uint8_t count = (uint8_t)ArgumentCount(sig).size();
  13.433 +      for (uint8_t i = 0; i < count; ++i) {
  13.434 +        *par++ = i;
  13.435 +      }
  13.436 +    }
  13.437 +  }
  13.438 +
  13.439 +  // Register module
  13.440 +  return dof_register(module, dof, moduleBaseAddress);
  13.441 +}
  13.442 +
  13.443 +
  13.444 +void DTraceJSDT::pd_dispose(int handle) {
  13.445 +  int fd;
  13.446 +  if (handle == -1) {
  13.447 +    return;
  13.448 +  }
  13.449 +  fd = dofhelper_open();
  13.450 +  if (fd < 0)
  13.451 +    return;
  13.452 +  ioctl(fd, DTRACEHIOC_REMOVE, handle);
  13.453 +  close(fd);
  13.454 +}
  13.455 +
  13.456 +jboolean DTraceJSDT::pd_is_supported() {
  13.457 +  int fd = dofhelper_open();
  13.458 +  if (fd < 0) {
  13.459 +    return false;
  13.460 +  }
  13.461 +  close(fd);
  13.462 +  return true;
  13.463 +}
  13.464 +
  13.465 +static const char* dofSecTypeFor(uint32_t type) {
  13.466 +  switch (type) {
  13.467 +    case 0:  return "DOF_SECT_NONE";
  13.468 +    case 1:  return "DOF_SECT_COMMENTS";
  13.469 +    case 2:  return "DOF_SECT_SOURCE";
  13.470 +    case 3:  return "DOF_SECT_ECBDESC";
  13.471 +    case 4:  return "DOF_SECT_PROBEDESC";
  13.472 +    case 5:  return "DOF_SECT_ACTDESC";
  13.473 +    case 6:  return "DOF_SECT_DIFOHDR";
  13.474 +    case 7:  return "DOF_SECT_DIF";
  13.475 +    case 8:  return "DOF_SECT_STRTAB";
  13.476 +    case 9:  return "DOF_SECT_VARTAB";
  13.477 +    case 10: return "DOF_SECT_RELTAB";
  13.478 +    case 11: return "DOF_SECT_TYPETAB";
  13.479 +    case 12: return "DOF_SECT_URELHDR";
  13.480 +    case 13: return "DOF_SECT_KRELHDR";
  13.481 +    case 14: return "DOF_SECT_OPTDESC";
  13.482 +    case 15: return "DOF_SECT_PROVIDER";
  13.483 +    case 16: return "DOF_SECT_PROBES";
  13.484 +    case 17: return "DOF_SECT_PRARGS";
  13.485 +    case 18: return "DOF_SECT_PROFFS";
  13.486 +    case 19: return "DOF_SECT_INTTAB";
  13.487 +    case 20: return "DOF_SECT_UTSNAME";
  13.488 +    case 21: return "DOF_SECT_XLTAB";
  13.489 +    case 22: return "DOF_SECT_XLMEMBERS";
  13.490 +    case 23: return "DOF_SECT_XLIMPORT";
  13.491 +    case 24: return "DOF_SECT_XLEXPORT";
  13.492 +    case 25: return "DOF_SECT_PREXPORT";
  13.493 +    case 26: return "DOF_SECT_PRENOFFS";
  13.494 +    default: return "<unknown>";
  13.495 +  }
  13.496 +}
  13.497 +
  13.498 +static void printDOFStringTabSec(void* dof, dof_sec_t* sec) {
  13.499 +  size_t tab = sec->dofs_offset;
  13.500 +  size_t limit = sec->dofs_size;
  13.501 +  tty->print_cr("//   String Table:");
  13.502 +  for (size_t idx = 0; idx < limit; /*empty*/) {
  13.503 +    char* str = ((char*)dof) + tab + idx;
  13.504 +    tty->print_cr("//   [0x%x + 0x%x] '%s'", tab, idx, str);
  13.505 +    idx += strlen(str) + 1;
  13.506 +  }
  13.507 +}
  13.508 +
  13.509 +static void printDOFProviderSec(void* dof, dof_sec_t* sec) {
  13.510 +  dof_provider_t* prov = (dof_provider_t*)((char*)dof + sec->dofs_offset);
  13.511 +  tty->print_cr("//   dof_provider_t {");
  13.512 +  tty->print_cr("//     dofpv_strtab = %d", prov->dofpv_strtab);
  13.513 +  tty->print_cr("//     dofpv_probes = %d", prov->dofpv_probes);
  13.514 +  tty->print_cr("//     dofpv_prargs = %d", prov->dofpv_prargs);
  13.515 +  tty->print_cr("//     dofpv_proffs = %d", prov->dofpv_proffs);
  13.516 +  tty->print_cr("//     dofpv_name = 0x%x", prov->dofpv_name);
  13.517 +  tty->print_cr("//     dofpv_provattr = 0x%08x", prov->dofpv_provattr);
  13.518 +  tty->print_cr("//     dofpv_modattr = 0x%08x", prov->dofpv_modattr);
  13.519 +  tty->print_cr("//     dofpv_funcattr = 0x%08x", prov->dofpv_funcattr);
  13.520 +  tty->print_cr("//     dofpv_nameattr = 0x%08x", prov->dofpv_nameattr);
  13.521 +  tty->print_cr("//     dofpv_argsattr = 0x%08x", prov->dofpv_argsattr);
  13.522 +  tty->print_cr("//   }");
  13.523 +}
  13.524 +
  13.525 +static void printDOFProbesSec(void* dof, dof_sec_t* sec) {
  13.526 +  size_t idx = sec->dofs_offset;
  13.527 +  size_t limit = idx + sec->dofs_size;
  13.528 +  for (size_t idx = sec->dofs_offset; idx < limit; idx += sec->dofs_entsize) {
  13.529 +    dof_probe_t* prb = (dof_probe_t*)((char*)dof + idx);
  13.530 +    tty->print_cr("//   dof_probe_t {");
  13.531 +    tty->print_cr("//     dofpr_addr = 0x%016llx", prb->dofpr_addr);
  13.532 +    tty->print_cr("//     dofpr_func = 0x%x", prb->dofpr_func);
  13.533 +    tty->print_cr("//     dofpr_name = 0x%x", prb->dofpr_name);
  13.534 +    tty->print_cr("//     dofpr_nargv = 0x%x", prb->dofpr_nargv);
  13.535 +    tty->print_cr("//     dofpr_xargv = 0x%x", prb->dofpr_xargv);
  13.536 +    tty->print_cr("//     dofpr_argidx = 0x%x", prb->dofpr_argidx);
  13.537 +    tty->print_cr("//     dofpr_offidx = 0x%x", prb->dofpr_offidx);
  13.538 +    tty->print_cr("//     dofpr_nargc = %d", prb->dofpr_nargc);
  13.539 +    tty->print_cr("//     dofpr_xargc = %d", prb->dofpr_xargc);
  13.540 +    tty->print_cr("//     dofpr_noffs = %d", prb->dofpr_noffs);
  13.541 +    tty->print_cr("//   }");
  13.542 +  }
  13.543 +}
  13.544 +
  13.545 +static void printDOFOffsetsSec(void* dof, dof_sec_t* sec) {
  13.546 +  size_t tab = sec->dofs_offset;
  13.547 +  size_t limit = sec->dofs_size;
  13.548 +  tty->print_cr("//   Offsets:");
  13.549 +  for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) {
  13.550 +    uint32_t* off = (uint32_t*)((char*)dof + tab + idx);
  13.551 +    tty->print_cr("//   [0x%x + 0x%x]: %d", tab, idx, *off);
  13.552 +  }
  13.553 +}
  13.554 +
  13.555 +static void printDOFArgsSec(void* dof, dof_sec_t* sec) {
  13.556 +  size_t tab = sec->dofs_offset;
  13.557 +  size_t limit = sec->dofs_size;
  13.558 +  tty->print_cr("//   Arguments:");
  13.559 +  for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) {
  13.560 +    uint8_t* arg = (uint8_t*)((char*)dof + tab + idx);
  13.561 +    tty->print_cr("//   [0x%x + 0x%x]: %d", tab, idx, *arg);
  13.562 +  }
  13.563 +}
  13.564 +
  13.565 +static void printDOFSection(void* dof, dof_sec_t* sec) {
  13.566 +  tty->print_cr("//   dof_sec_t {");
  13.567 +  tty->print_cr("//     dofs_type = 0x%x /* %s */",
  13.568 +                sec->dofs_type, dofSecTypeFor(sec->dofs_type));
  13.569 +  tty->print_cr("//     dofs_align = %d", sec->dofs_align);
  13.570 +  tty->print_cr("//     dofs_flags = 0x%x", sec->dofs_flags);
  13.571 +  tty->print_cr("//     dofs_entsize = %d", sec->dofs_entsize);
  13.572 +  tty->print_cr("//     dofs_offset = 0x%llx", sec->dofs_offset);
  13.573 +  tty->print_cr("//     dofs_size = %lld", sec->dofs_size);
  13.574 +  tty->print_cr("//   }");
  13.575 +  switch (sec->dofs_type) {
  13.576 +    case DOF_SECT_STRTAB:    printDOFStringTabSec(dof, sec); break;
  13.577 +    case DOF_SECT_PROVIDER:  printDOFProviderSec(dof, sec);  break;
  13.578 +    case DOF_SECT_PROBES:    printDOFProbesSec(dof, sec);    break;
  13.579 +    case DOF_SECT_PROFFS:    printDOFOffsetsSec(dof, sec);   break;
  13.580 +    case DOF_SECT_PRARGS:    printDOFArgsSec(dof, sec);      break;
  13.581 +    default: tty->print_cr("//   <section type not recognized>");
  13.582 +  }
  13.583 +}
  13.584 +
  13.585 +static void printDOFHeader(dof_hdr_t* hdr) {
  13.586 +  tty->print_cr("//   dof_hdr_t {");
  13.587 +  tty->print_cr("//     dofh_ident[DOF_ID_MAG0] = 0x%x",
  13.588 +                hdr->dofh_ident[DOF_ID_MAG0]);
  13.589 +  tty->print_cr("//     dofh_ident[DOF_ID_MAG1] = 0x%x",
  13.590 +                hdr->dofh_ident[DOF_ID_MAG1]);
  13.591 +  tty->print_cr("//     dofh_ident[DOF_ID_MAG2] = 0x%x",
  13.592 +                hdr->dofh_ident[DOF_ID_MAG2]);
  13.593 +  tty->print_cr("//     dofh_ident[DOF_ID_MAG3] = 0x%x",
  13.594 +                hdr->dofh_ident[DOF_ID_MAG3]);
  13.595 +  tty->print_cr("//     dofh_ident[DOF_ID_MODEL] = 0x%x",
  13.596 +                hdr->dofh_ident[DOF_ID_MODEL]);
  13.597 +  tty->print_cr("//     dofh_ident[DOF_ID_ENCODING] = 0x%x",
  13.598 +                hdr->dofh_ident[DOF_ID_ENCODING]);
  13.599 +  tty->print_cr("//     dofh_ident[DOF_ID_VERSION] = 0x%x",
  13.600 +                hdr->dofh_ident[DOF_ID_VERSION]);
  13.601 +  tty->print_cr("//     dofh_ident[DOF_ID_DIFVERS] = 0x%x",
  13.602 +                hdr->dofh_ident[DOF_ID_DIFVERS]);
  13.603 +  tty->print_cr("//     dofh_flags = 0x%x", hdr->dofh_flags);
  13.604 +  tty->print_cr("//     dofh_hdrsize = %d", hdr->dofh_hdrsize);
  13.605 +  tty->print_cr("//     dofh_secsize = %d", hdr->dofh_secsize);
  13.606 +  tty->print_cr("//     dofh_secnum = %d", hdr->dofh_secnum);
  13.607 +  tty->print_cr("//     dofh_secoff = %lld", hdr->dofh_secoff);
  13.608 +  tty->print_cr("//     dofh_loadsz = %lld", hdr->dofh_loadsz);
  13.609 +  tty->print_cr("//     dofh_filesz = %lld", hdr->dofh_filesz);
  13.610 +  tty->print_cr("//   }");
  13.611 +}
  13.612 +
  13.613 +static void printDOF(void* dof) {
  13.614 +  dof_hdr_t* hdr = (dof_hdr_t*)dof;
  13.615 +  printDOFHeader(hdr);
  13.616 +  for (int i = 0; i < hdr->dofh_secnum; ++i) {
  13.617 +    dof_sec_t* sec =
  13.618 +      (dof_sec_t*)((char*)dof + sizeof(dof_hdr_t) + i * sizeof(dof_sec_t));
  13.619 +    tty->print_cr("//   [Section #%d]", i);
  13.620 +    printDOFSection(dof, sec);
  13.621 +  }
  13.622 +}
  13.623 +
  13.624 +/**
  13.625 + * This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
  13.626 + *   <hex-address>: 8 * <hex-halfword> <ascii translation>
  13.627 + * example:
  13.628 + * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000  .DOF............
  13.629 + * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005  .......@... ....
  13.630 + * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d  .......@.......]
  13.631 + * ...
  13.632 + */
  13.633 +static void printDOFRawData(void* dof) {
  13.634 +  size_t size = ((dof_hdr_t*)dof)->dofh_loadsz;
  13.635 +  size_t limit = (size + 16) / 16 * 16;
  13.636 +  for (size_t i = 0; i < limit; ++i) {
  13.637 +    if (i % 16 == 0) {
  13.638 +      tty->print("%07x:", i);
  13.639 +    }
  13.640 +    if (i % 2 == 0) {
  13.641 +      tty->print(" ");
  13.642 +    }
  13.643 +    if (i < size) {
  13.644 +      tty->print("%02x", ((unsigned char*)dof)[i]);
  13.645 +    } else {
  13.646 +      tty->print("  ");
  13.647 +    }
  13.648 +    if ((i + 1) % 16 == 0) {
  13.649 +      tty->print("  ");
  13.650 +      for (size_t j = 0; j < 16; ++j) {
  13.651 +        size_t idx = i + j - 15;
  13.652 +        char c = ((char*)dof)[idx];
  13.653 +        if (idx < size) {
  13.654 +          tty->print("%c", c >= 32 && c <= 126 ? c : '.');
  13.655 +        }
  13.656 +      }
  13.657 +      tty->print_cr("");
  13.658 +    }
  13.659 +  }
  13.660 +  tty->print_cr("");
  13.661 +}
  13.662 +
  13.663 +static void printDOFHelper(dof_helper_t* helper) {
  13.664 +  tty->print_cr("// dof_helper_t {");
  13.665 +  tty->print_cr("//   dofhp_mod = \"%s\"", helper->dofhp_mod);
  13.666 +  tty->print_cr("//   dofhp_addr = 0x%016llx", helper->dofhp_addr);
  13.667 +  tty->print_cr("//   dofhp_dof = 0x%016llx", helper->dofhp_dof);
  13.668 +  printDOF((void*)helper->dofhp_dof);
  13.669 +  tty->print_cr("// }");
  13.670 +  printDOFRawData((void*)helper->dofhp_dof);
  13.671 +}
  13.672 +
  13.673 +#else // ndef HAVE_DTRACE_H
  13.674 +
  13.675 +// Get here if we're not building on at least Solaris 10
  13.676 +int DTraceJSDT::pd_activate(
  13.677 +  void* baseAddress, jstring module,
  13.678 +  jint provider_count, JVM_DTraceProvider* providers) {
  13.679 +  return -1;
  13.680 +}
  13.681 +
  13.682 +void DTraceJSDT::pd_dispose(int handle) {
  13.683 +}
  13.684 +
  13.685 +jboolean DTraceJSDT::pd_is_supported() {
  13.686 +  return false;
  13.687 +}
  13.688 +#endif
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/os/windows/vm/dtraceJSDT_windows.cpp	Thu Apr 17 22:18:15 2008 -0400
    14.3 @@ -0,0 +1,39 @@
    14.4 +/*
    14.5 + * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + *
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + *
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + *
   14.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   14.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   14.24 + * have any questions.
   14.25 + *
   14.26 + */
   14.27 +
   14.28 +#include "incls/_precompiled.incl"
   14.29 +#include "incls/_dtraceJSDT_windows.cpp.incl"
   14.30 +
   14.31 +int DTraceJSDT::pd_activate(
   14.32 +    void* baseAddress, jstring module,
   14.33 +    jint providers_count, JVM_DTraceProvider* providers) {
   14.34 +  return -1;
   14.35 +}
   14.36 +
   14.37 +void DTraceJSDT::pd_dispose(int handle) {
   14.38 +}
   14.39 +
   14.40 +jboolean DTraceJSDT::pd_is_supported() {
   14.41 +  return false;
   14.42 +}
    15.1 --- a/src/share/vm/asm/codeBuffer.hpp	Wed Apr 16 17:36:29 2008 -0400
    15.2 +++ b/src/share/vm/asm/codeBuffer.hpp	Thu Apr 17 22:18:15 2008 -0400
    15.3 @@ -36,6 +36,7 @@
    15.4                   Verified_Entry,
    15.5                   Frame_Complete, // Offset in the code where the frame setup is (for forte stackwalks) is complete
    15.6                   OSR_Entry,
    15.7 +                 Dtrace_trap = OSR_Entry,  // dtrace probes can never have an OSR entry so reuse it
    15.8                   Exceptions,     // Offset where exception handler lives
    15.9                   Deopt,          // Offset where deopt handler lives
   15.10                   max_Entries };
    16.1 --- a/src/share/vm/code/nmethod.cpp	Wed Apr 16 17:36:29 2008 -0400
    16.2 +++ b/src/share/vm/code/nmethod.cpp	Thu Apr 17 22:18:15 2008 -0400
    16.3 @@ -27,7 +27,6 @@
    16.4  
    16.5  #ifdef DTRACE_ENABLED
    16.6  
    16.7 -
    16.8  // Only bother with this argument setup if dtrace is available
    16.9  
   16.10  HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load,
   16.11 @@ -438,7 +437,6 @@
   16.12    {
   16.13      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   16.14      int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
   16.15 -    const int dummy = -1;               // Flag to force proper "operator new"
   16.16      CodeOffsets offsets;
   16.17      offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
   16.18      offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
   16.19 @@ -461,6 +459,41 @@
   16.20    return nm;
   16.21  }
   16.22  
   16.23 +#ifdef HAVE_DTRACE_H
   16.24 +nmethod* nmethod::new_dtrace_nmethod(methodHandle method,
   16.25 +                                     CodeBuffer *code_buffer,
   16.26 +                                     int vep_offset,
   16.27 +                                     int trap_offset,
   16.28 +                                     int frame_complete,
   16.29 +                                     int frame_size) {
   16.30 +  // create nmethod
   16.31 +  nmethod* nm = NULL;
   16.32 +  {
   16.33 +    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   16.34 +    int nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
   16.35 +    CodeOffsets offsets;
   16.36 +    offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
   16.37 +    offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset);
   16.38 +    offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
   16.39 +
   16.40 +    nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size);
   16.41 +
   16.42 +    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
   16.43 +    if (PrintAssembly && nm != NULL)
   16.44 +      Disassembler::decode(nm);
   16.45 +  }
   16.46 +  // verify nmethod
   16.47 +  debug_only(if (nm) nm->verify();) // might block
   16.48 +
   16.49 +  if (nm != NULL) {
   16.50 +    nm->log_new_nmethod();
   16.51 +  }
   16.52 +
   16.53 +  return nm;
   16.54 +}
   16.55 +
   16.56 +#endif // def HAVE_DTRACE_H
   16.57 +
   16.58  nmethod* nmethod::new_nmethod(methodHandle method,
   16.59    int compile_id,
   16.60    int entry_bci,
   16.61 @@ -558,6 +591,9 @@
   16.62      _exception_offset        = 0;
   16.63      _deoptimize_offset       = 0;
   16.64      _orig_pc_offset          = 0;
   16.65 +#ifdef HAVE_DTRACE_H
   16.66 +    _trap_offset             = 0;
   16.67 +#endif // def HAVE_DTRACE_H
   16.68      _stub_offset             = data_offset();
   16.69      _consts_offset           = data_offset();
   16.70      _scopes_data_offset      = data_offset();
   16.71 @@ -615,6 +651,90 @@
   16.72    Events::log("Create nmethod " INTPTR_FORMAT, this);
   16.73  }
   16.74  
   16.75 +// For dtrace wrappers
   16.76 +#ifdef HAVE_DTRACE_H
   16.77 +nmethod::nmethod(
   16.78 +  methodOop method,
   16.79 +  int nmethod_size,
   16.80 +  CodeOffsets* offsets,
   16.81 +  CodeBuffer* code_buffer,
   16.82 +  int frame_size)
   16.83 +  : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
   16.84 +             nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
   16.85 +  _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)),
   16.86 +  _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1))
   16.87 +{
   16.88 +  {
   16.89 +    debug_only(No_Safepoint_Verifier nsv;)
   16.90 +    assert_locked_or_safepoint(CodeCache_lock);
   16.91 +
   16.92 +    NOT_PRODUCT(_has_debug_info = false; )
   16.93 +    _method                  = method;
   16.94 +    _entry_bci               = InvocationEntryBci;
   16.95 +    _link                    = NULL;
   16.96 +    _compiler                = NULL;
   16.97 +    // We have no exception handler or deopt handler make the
   16.98 +    // values something that will never match a pc like the nmethod vtable entry
   16.99 +    _exception_offset        = 0;
  16.100 +    _deoptimize_offset       = 0;
  16.101 +    _trap_offset             = offsets->value(CodeOffsets::Dtrace_trap);
  16.102 +    _orig_pc_offset          = 0;
  16.103 +    _stub_offset             = data_offset();
  16.104 +    _consts_offset           = data_offset();
  16.105 +    _scopes_data_offset      = data_offset();
  16.106 +    _scopes_pcs_offset       = _scopes_data_offset;
  16.107 +    _dependencies_offset     = _scopes_pcs_offset;
  16.108 +    _handler_table_offset    = _dependencies_offset;
  16.109 +    _nul_chk_table_offset    = _handler_table_offset;
  16.110 +    _nmethod_end_offset      = _nul_chk_table_offset;
  16.111 +    _compile_id              = 0;  // default
  16.112 +    _comp_level              = CompLevel_none;
  16.113 +    _entry_point             = instructions_begin();
  16.114 +    _verified_entry_point    = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry);
  16.115 +    _osr_entry_point         = NULL;
  16.116 +    _exception_cache         = NULL;
  16.117 +    _pc_desc_cache.reset_to(NULL);
  16.118 +
  16.119 +    flags.clear();
  16.120 +    flags.state              = alive;
  16.121 +    _markedForDeoptimization = 0;
  16.122 +
  16.123 +    _lock_count = 0;
  16.124 +    _stack_traversal_mark    = 0;
  16.125 +
  16.126 +    code_buffer->copy_oops_to(this);
  16.127 +    debug_only(check_store();)
  16.128 +    CodeCache::commit(this);
  16.129 +    VTune::create_nmethod(this);
  16.130 +  }
  16.131 +
  16.132 +  if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
  16.133 +    ttyLocker ttyl;  // keep the following output all in one block
  16.134 +    // This output goes directly to the tty, not the compiler log.
  16.135 +    // To enable tools to match it up with the compilation activity,
  16.136 +    // be sure to tag this tty output with the compile ID.
  16.137 +    if (xtty != NULL) {
  16.138 +      xtty->begin_head("print_dtrace_nmethod");
  16.139 +      xtty->method(_method);
  16.140 +      xtty->stamp();
  16.141 +      xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this);
  16.142 +    }
  16.143 +    // print the header part first
  16.144 +    print();
  16.145 +    // then print the requested information
  16.146 +    if (PrintNMethods) {
  16.147 +      print_code();
  16.148 +    }
  16.149 +    if (PrintRelocations) {
  16.150 +      print_relocations();
  16.151 +    }
  16.152 +    if (xtty != NULL) {
  16.153 +      xtty->tail("print_dtrace_nmethod");
  16.154 +    }
  16.155 +  }
  16.156 +  Events::log("Create nmethod " INTPTR_FORMAT, this);
  16.157 +}
  16.158 +#endif // def HAVE_DTRACE_H
  16.159  
  16.160  void* nmethod::operator new(size_t size, int nmethod_size) {
  16.161    // Always leave some room in the CodeCache for I2C/C2I adapters
  16.162 @@ -658,6 +778,9 @@
  16.163      _link                    = NULL;
  16.164      _compiler                = compiler;
  16.165      _orig_pc_offset          = orig_pc_offset;
  16.166 +#ifdef HAVE_DTRACE_H
  16.167 +    _trap_offset             = 0;
  16.168 +#endif // def HAVE_DTRACE_H
  16.169      _stub_offset             = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
  16.170  
  16.171      // Exception handler and deopt handler are in the stub section
  16.172 @@ -1885,7 +2008,6 @@
  16.173    } else if (is_compiled_by_c2()) {
  16.174      tty->print("(c2) ");
  16.175    } else {
  16.176 -    assert(is_native_method(), "Who else?");
  16.177      tty->print("(nm) ");
  16.178    }
  16.179  
    17.1 --- a/src/share/vm/code/nmethod.hpp	Wed Apr 16 17:36:29 2008 -0400
    17.2 +++ b/src/share/vm/code/nmethod.hpp	Thu Apr 17 22:18:15 2008 -0400
    17.3 @@ -140,6 +140,9 @@
    17.4    int _exception_offset;
    17.5    // All deoptee's will resume execution at this location described by this offset
    17.6    int _deoptimize_offset;
    17.7 +#ifdef HAVE_DTRACE_H
    17.8 +  int _trap_offset;
    17.9 +#endif // def HAVE_DTRACE_H
   17.10    int _stub_offset;
   17.11    int _consts_offset;
   17.12    int _scopes_data_offset;
   17.13 @@ -211,6 +214,15 @@
   17.14            ByteSize basic_lock_sp_offset,       /* synchronized natives only */
   17.15            OopMapSet* oop_maps);
   17.16  
   17.17 +#ifdef HAVE_DTRACE_H
   17.18 +  // For native wrappers
   17.19 +  nmethod(methodOop method,
   17.20 +          int nmethod_size,
   17.21 +          CodeOffsets* offsets,
   17.22 +          CodeBuffer *code_buffer,
   17.23 +          int frame_size);
   17.24 +#endif // def HAVE_DTRACE_H
   17.25 +
   17.26    // Creation support
   17.27    nmethod(methodOop method,
   17.28            int nmethod_size,
   17.29 @@ -272,6 +284,22 @@
   17.30                                       ByteSize basic_lock_sp_offset,
   17.31                                       OopMapSet* oop_maps);
   17.32  
   17.33 +#ifdef HAVE_DTRACE_H
   17.34 +  // The method we generate for a dtrace probe has to look
   17.35 +  // like an nmethod as far as the rest of the system is concerned
   17.36 +  // which is somewhat unfortunate.
   17.37 +  static nmethod* new_dtrace_nmethod(methodHandle method,
   17.38 +                                     CodeBuffer *code_buffer,
   17.39 +                                     int vep_offset,
   17.40 +                                     int trap_offset,
   17.41 +                                     int frame_complete,
   17.42 +                                     int frame_size);
   17.43 +
   17.44 +  int trap_offset() const      { return _trap_offset; }
   17.45 +  address trap_address() const { return code_begin() + _trap_offset; }
   17.46 +
   17.47 +#endif // def HAVE_DTRACE_H
   17.48 +
   17.49    // accessors
   17.50    methodOop method() const                        { return _method; }
   17.51    AbstractCompiler* compiler() const              { return _compiler; }
    18.1 --- a/src/share/vm/includeDB_core	Wed Apr 16 17:36:29 2008 -0400
    18.2 +++ b/src/share/vm/includeDB_core	Thu Apr 17 22:18:15 2008 -0400
    18.3 @@ -1497,6 +1497,30 @@
    18.4  dtraceAttacher.cpp                      vmThread.hpp
    18.5  dtraceAttacher.cpp                      vm_operations.hpp
    18.6  
    18.7 +dtraceJSDT.cpp                          allocation.hpp
    18.8 +dtraceJSDT.cpp                          codeBlob.hpp
    18.9 +dtraceJSDT.cpp                          dtraceJSDT.hpp
   18.10 +dtraceJSDT.cpp                          exceptions.hpp
   18.11 +dtraceJSDT.cpp                          globalDefinitions.hpp
   18.12 +dtraceJSDT.cpp                          javaClasses.hpp
   18.13 +dtraceJSDT.cpp                          jniHandles.hpp
   18.14 +dtraceJSDT.cpp                          jvm.h
   18.15 +dtraceJSDT.cpp                          os.hpp
   18.16 +dtraceJSDT.cpp                          utf8.hpp
   18.17 +
   18.18 +dtraceJSDT.hpp                          nativeInst_<arch>.hpp
   18.19 +dtraceJSDT.hpp                          nmethod.hpp
   18.20 +
   18.21 +dtraceJSDT_<os_family>.cpp              allocation.hpp
   18.22 +dtraceJSDT_<os_family>.cpp              codeBlob.hpp
   18.23 +dtraceJSDT_<os_family>.cpp              dtraceJSDT.hpp
   18.24 +dtraceJSDT_<os_family>.cpp              globalDefinitions.hpp
   18.25 +dtraceJSDT_<os_family>.cpp              javaClasses.hpp
   18.26 +dtraceJSDT_<os_family>.cpp              jniHandles.hpp
   18.27 +dtraceJSDT_<os_family>.cpp              jvm.h
   18.28 +dtraceJSDT_<os_family>.cpp              os.hpp
   18.29 +dtraceJSDT_<os_family>.cpp              signature.hpp
   18.30 +
   18.31  // dump is jck optional, put cpp deps in includeDB_features
   18.32  
   18.33  events.cpp                              allocation.inline.hpp
   18.34 @@ -2400,6 +2424,7 @@
   18.35  jvm.cpp                                 collectedHeap.inline.hpp
   18.36  jvm.cpp                                 copy.hpp
   18.37  jvm.cpp                                 defaultStream.hpp
   18.38 +jvm.cpp                                 dtraceJSDT.hpp
   18.39  jvm.cpp                                 events.hpp
   18.40  jvm.cpp                                 handles.inline.hpp
   18.41  jvm.cpp                                 histogram.hpp
    19.1 --- a/src/share/vm/oops/methodOop.cpp	Wed Apr 16 17:36:29 2008 -0400
    19.2 +++ b/src/share/vm/oops/methodOop.cpp	Thu Apr 17 22:18:15 2008 -0400
    19.3 @@ -672,9 +672,6 @@
    19.4  }
    19.5  
    19.6  address methodOopDesc::make_adapters(methodHandle mh, TRAPS) {
    19.7 -  // If running -Xint we need no adapters.
    19.8 -  if (Arguments::mode() == Arguments::_int) return NULL;
    19.9 -
   19.10    // Adapters for compiled code are made eagerly here.  They are fairly
   19.11    // small (generally < 100 bytes) and quick to make (and cached and shared)
   19.12    // so making them eagerly shouldn't be too expensive.
    20.1 --- a/src/share/vm/prims/jvm.cpp	Wed Apr 16 17:36:29 2008 -0400
    20.2 +++ b/src/share/vm/prims/jvm.cpp	Thu Apr 17 22:18:15 2008 -0400
    20.3 @@ -4168,6 +4168,36 @@
    20.4    return res == oldVal;
    20.5  JVM_END
    20.6  
    20.7 +// DTrace ///////////////////////////////////////////////////////////////////
    20.8 +
    20.9 +JVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env))
   20.10 +  JVMWrapper("JVM_DTraceGetVersion");
   20.11 +  return (jint)JVM_TRACING_DTRACE_VERSION;
   20.12 +JVM_END
   20.13 +
   20.14 +JVM_ENTRY(jlong,JVM_DTraceActivate(
   20.15 +    JNIEnv* env, jint version, jstring module_name, jint providers_count,
   20.16 +    JVM_DTraceProvider* providers))
   20.17 +  JVMWrapper("JVM_DTraceActivate");
   20.18 +  return DTraceJSDT::activate(
   20.19 +    version, module_name, providers_count, providers, CHECK_0);
   20.20 +JVM_END
   20.21 +
   20.22 +JVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method))
   20.23 +  JVMWrapper("JVM_DTraceIsProbeEnabled");
   20.24 +  return DTraceJSDT::is_probe_enabled(method);
   20.25 +JVM_END
   20.26 +
   20.27 +JVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle))
   20.28 +  JVMWrapper("JVM_DTraceDispose");
   20.29 +  DTraceJSDT::dispose(handle);
   20.30 +JVM_END
   20.31 +
   20.32 +JVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env))
   20.33 +  JVMWrapper("JVM_DTraceIsSupported");
   20.34 +  return DTraceJSDT::is_supported();
   20.35 +JVM_END
   20.36 +
   20.37  // Returns an array of all live Thread objects (VM internal JavaThreads,
   20.38  // jvmti agent threads, and JNI attaching threads  are skipped)
   20.39  // See CR 6404306 regarding JNI attaching threads
   20.40 @@ -4496,3 +4526,4 @@
   20.41  #endif // KERNEL
   20.42  }
   20.43  JVM_END
   20.44 +
    21.1 --- a/src/share/vm/prims/jvm.h	Wed Apr 16 17:36:29 2008 -0400
    21.2 +++ b/src/share/vm/prims/jvm.h	Thu Apr 17 22:18:15 2008 -0400
    21.3 @@ -606,6 +606,83 @@
    21.4  JNIEXPORT jboolean JNICALL
    21.5  JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fldID, jlong oldVal, jlong newVal);
    21.6  
    21.7 +/*
    21.8 + * com.sun.dtrace.jsdt support
    21.9 + */
   21.10 +
   21.11 +#define JVM_TRACING_DTRACE_VERSION 1
   21.12 +
   21.13 +/*
   21.14 + * Structure to pass one probe description to JVM.
   21.15 + *
   21.16 + * The VM will overwrite the definition of the referenced method with
   21.17 + * code that will fire the probe.
   21.18 + */
   21.19 +typedef struct {
   21.20 +    jmethodID method;
   21.21 +    jstring   function;
   21.22 +    jstring   name;
   21.23 +    void*     reserved[4];     // for future use
   21.24 +} JVM_DTraceProbe;
   21.25 +
   21.26 +/**
   21.27 + * Encapsulates the stability ratings for a DTrace provider field
   21.28 + */
   21.29 +typedef struct {
   21.30 +    jint nameStability;
   21.31 +    jint dataStability;
   21.32 +    jint dependencyClass;
   21.33 +} JVM_DTraceInterfaceAttributes;
   21.34 +
   21.35 +/*
   21.36 + * Structure to pass one provider description to JVM
   21.37 + */
   21.38 +typedef struct {
   21.39 +    jstring                       name;
   21.40 +    JVM_DTraceProbe*              probes;
   21.41 +    jint                          probe_count;
   21.42 +    JVM_DTraceInterfaceAttributes providerAttributes;
   21.43 +    JVM_DTraceInterfaceAttributes moduleAttributes;
   21.44 +    JVM_DTraceInterfaceAttributes functionAttributes;
   21.45 +    JVM_DTraceInterfaceAttributes nameAttributes;
   21.46 +    JVM_DTraceInterfaceAttributes argsAttributes;
   21.47 +    void*                         reserved[4]; // for future use
   21.48 +} JVM_DTraceProvider;
   21.49 +
   21.50 +/*
   21.51 + * Get the version number the JVM was built with
   21.52 + */
   21.53 +JNIEXPORT jint JNICALL
   21.54 +JVM_DTraceGetVersion(JNIEnv* env);
   21.55 +
   21.56 +/*
   21.57 + * Register new probe with given signature, return global handle
   21.58 + *
   21.59 + * The version passed in is the version that the library code was
   21.60 + * built with.
   21.61 + */
   21.62 +JNIEXPORT jlong JNICALL
   21.63 +JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name,
   21.64 +  jint providers_count, JVM_DTraceProvider* providers);
   21.65 +
   21.66 +/*
   21.67 + * Check JSDT probe
   21.68 + */
   21.69 +JNIEXPORT jboolean JNICALL
   21.70 +JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method);
   21.71 +
   21.72 +/*
   21.73 + * Destroy custom DOF
   21.74 + */
   21.75 +JNIEXPORT void JNICALL
   21.76 +JVM_DTraceDispose(JNIEnv* env, jlong handle);
   21.77 +
   21.78 +/*
   21.79 + * Check to see if DTrace is supported by OS
   21.80 + */
   21.81 +JNIEXPORT jboolean JNICALL
   21.82 +JVM_DTraceIsSupported(JNIEnv* env);
   21.83 +
   21.84  /*************************************************************************
   21.85   PART 2: Support for the Verifier and Class File Format Checker
   21.86   ************************************************************************/
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/share/vm/runtime/dtraceJSDT.cpp	Thu Apr 17 22:18:15 2008 -0400
    22.3 @@ -0,0 +1,117 @@
    22.4 +/*
    22.5 + * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.
   22.11 + *
   22.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.15 + * version 2 for more details (a copy is included in the LICENSE file that
   22.16 + * accompanied this code).
   22.17 + *
   22.18 + * You should have received a copy of the GNU General Public License version
   22.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.21 + *
   22.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   22.24 + * have any questions.
   22.25 + *
   22.26 + */
   22.27 +
   22.28 +#include "incls/_precompiled.incl"
   22.29 +#include "incls/_dtraceJSDT.cpp.incl"
   22.30 +
   22.31 +#ifdef HAVE_DTRACE_H
   22.32 +
   22.33 +jlong DTraceJSDT::activate(
   22.34 +    jint version, jstring module_name, jint providers_count,
   22.35 +    JVM_DTraceProvider* providers, TRAPS) {
   22.36 +
   22.37 +  size_t count = 0;
   22.38 +  RegisteredProbes* probes = NULL;
   22.39 +
   22.40 +  if (!is_supported()) {
   22.41 +    return 0;
   22.42 +  }
   22.43 +
   22.44 +  assert(module_name != NULL, "valid module name");
   22.45 +  assert(providers != NULL, "valid provider array");
   22.46 +
   22.47 +  for (int i = 0; i < providers_count; ++i) {
   22.48 +    count += providers[i].probe_count;
   22.49 +  }
   22.50 +  probes = new RegisteredProbes(count);
   22.51 +  count = 0;
   22.52 +
   22.53 +  for (int i = 0; i < providers_count; ++i) {
   22.54 +    assert(providers[i].name != NULL, "valid provider name");
   22.55 +    assert(providers[i].probe_count == 0 || providers[i].probes != NULL,
   22.56 +           "valid probe count");
   22.57 +    for (int j = 0; j < providers[i].probe_count; ++j) {
   22.58 +      JVM_DTraceProbe* probe = &(providers[i].probes[j]);
   22.59 +      assert(probe != NULL, "valid probe");
   22.60 +      assert(probe->method != NULL, "valid method");
   22.61 +      assert(probe->name != NULL, "valid probe name");
   22.62 +      assert(probe->function != NULL, "valid probe function spec");
   22.63 +      methodHandle h_method =
   22.64 +        methodHandle(THREAD, JNIHandles::resolve_jmethod_id(probe->method));
   22.65 +      nmethod* nm = AdapterHandlerLibrary::create_dtrace_nmethod(h_method);
   22.66 +      h_method()->set_not_compilable(CompLevel_highest_tier);
   22.67 +      h_method()->set_code(h_method, nm);
   22.68 +      probes->nmethod_at_put(count++, nm);
   22.69 +    }
   22.70 +  }
   22.71 +
   22.72 +  int handle = pd_activate((void*)probes,
   22.73 +    module_name, providers_count, providers);
   22.74 +  if (handle <= 0) {
   22.75 +    delete probes;
   22.76 +    THROW_MSG_0(vmSymbols::java_lang_RuntimeException(),
   22.77 +      "Unable to register DTrace probes (internal error).");
   22.78 +  }
   22.79 +  probes->set_helper_handle(handle);
   22.80 +  return RegisteredProbes::toOpaqueProbes(probes);
   22.81 +}
   22.82 +
   22.83 +jboolean DTraceJSDT::is_probe_enabled(jmethodID method) {
   22.84 +  methodOop m = JNIHandles::resolve_jmethod_id(method);
   22.85 +  return nativeInstruction_at(m->code()->trap_address())->is_dtrace_trap();
   22.86 +}
   22.87 +
   22.88 +void DTraceJSDT::dispose(OpaqueProbes probes) {
   22.89 +  RegisteredProbes* p = RegisteredProbes::toRegisteredProbes(probes);
   22.90 +  if (probes != -1 && p != NULL) {
   22.91 +    pd_dispose(p->helper_handle());
   22.92 +    delete p;
   22.93 +  }
   22.94 +}
   22.95 +
   22.96 +jboolean DTraceJSDT::is_supported() {
   22.97 +  return pd_is_supported();
   22.98 +}
   22.99 +
  22.100 +#else // HAVE_DTRACE_H
  22.101 +
  22.102 +jlong DTraceJSDT::activate(
  22.103 +    jint version, jstring module_name, jint providers_count,
  22.104 +    JVM_DTraceProvider* providers, TRAPS) {
  22.105 +  return 0;
  22.106 +}
  22.107 +
  22.108 +jboolean DTraceJSDT::is_probe_enabled(jmethodID method) {
  22.109 +  return false;
  22.110 +}
  22.111 +
  22.112 +void DTraceJSDT::dispose(OpaqueProbes probes) {
  22.113 +  return;
  22.114 +}
  22.115 +
  22.116 +jboolean DTraceJSDT::is_supported() {
  22.117 +  return false;
  22.118 +}
  22.119 +
  22.120 +#endif // ndef HAVE_DTRACE_H
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/share/vm/runtime/dtraceJSDT.hpp	Thu Apr 17 22:18:15 2008 -0400
    23.3 @@ -0,0 +1,89 @@
    23.4 +/*
    23.5 + * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.7 + *
    23.8 + * This code is free software; you can redistribute it and/or modify it
    23.9 + * under the terms of the GNU General Public License version 2 only, as
   23.10 + * published by the Free Software Foundation.
   23.11 + *
   23.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   23.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   23.15 + * version 2 for more details (a copy is included in the LICENSE file that
   23.16 + * accompanied this code).
   23.17 + *
   23.18 + * You should have received a copy of the GNU General Public License version
   23.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   23.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   23.21 + *
   23.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   23.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   23.24 + * have any questions.
   23.25 + *
   23.26 + */
   23.27 +
   23.28 +class RegisteredProbes;
   23.29 +typedef jlong OpaqueProbes;
   23.30 +
   23.31 +class DTraceJSDT : AllStatic {
   23.32 + private:
   23.33 +
   23.34 +  static int pd_activate(void* moduleBaseAddress, jstring module,
   23.35 +      jint providers_count, JVM_DTraceProvider* providers);
   23.36 +  static void pd_dispose(int handle);
   23.37 +  static jboolean pd_is_supported();
   23.38 +
   23.39 + public:
   23.40 +
   23.41 +  static OpaqueProbes activate(
   23.42 +      jint version, jstring module_name, jint providers_count,
   23.43 +      JVM_DTraceProvider* providers, TRAPS);
   23.44 +  static jboolean is_probe_enabled(jmethodID method);
   23.45 +  static void dispose(OpaqueProbes handle);
   23.46 +  static jboolean is_supported();
   23.47 +};
   23.48 +
   23.49 +class RegisteredProbes : public CHeapObj {
   23.50 + private:
   23.51 +  nmethod** _nmethods;      // all the probe methods
   23.52 +  size_t    _count;         // number of probe methods
   23.53 +  int       _helper_handle; // DTrace-assigned identifier
   23.54 +
   23.55 + public:
   23.56 +  RegisteredProbes(size_t count) {
   23.57 +    _count = count;
   23.58 +    _nmethods = NEW_C_HEAP_ARRAY(nmethod*, count);
   23.59 +  }
   23.60 +
   23.61 +  ~RegisteredProbes() {
   23.62 +    for (size_t i = 0; i < _count; ++i) {
   23.63 +      // Let the sweeper reclaim it
   23.64 +      _nmethods[i]->make_not_entrant();
   23.65 +      _nmethods[i]->method()->clear_code();
   23.66 +    }
   23.67 +    FREE_C_HEAP_ARRAY(nmethod*, _nmethods);
   23.68 +    _nmethods = NULL;
   23.69 +    _count = 0;
   23.70 +  }
   23.71 +
   23.72 +  static RegisteredProbes* toRegisteredProbes(OpaqueProbes p) {
   23.73 +    return (RegisteredProbes*)(intptr_t)p;
   23.74 +  }
   23.75 +
   23.76 +  static OpaqueProbes toOpaqueProbes(RegisteredProbes* p) {
   23.77 +    return (OpaqueProbes)(intptr_t)p;
   23.78 +  }
   23.79 +
   23.80 +  void set_helper_handle(int handle) { _helper_handle = handle; }
   23.81 +  int helper_handle() const { return _helper_handle; }
   23.82 +
   23.83 +  nmethod* nmethod_at(size_t i) {
   23.84 +    assert(i >= 0 && i < _count, "bad nmethod index");
   23.85 +    return _nmethods[i];
   23.86 +  }
   23.87 +
   23.88 +  void nmethod_at_put(size_t i, nmethod* nm) {
   23.89 +    assert(i >= 0 && i < _count, "bad nmethod index");
   23.90 +    _nmethods[i] = nm;
   23.91 +  }
   23.92 +};
    24.1 --- a/src/share/vm/runtime/globals.hpp	Wed Apr 16 17:36:29 2008 -0400
    24.2 +++ b/src/share/vm/runtime/globals.hpp	Thu Apr 17 22:18:15 2008 -0400
    24.3 @@ -3188,6 +3188,9 @@
    24.4    product(bool, RelaxAccessControlCheck, false,                             \
    24.5            "Relax the access control checks in the verifier")                \
    24.6                                                                              \
    24.7 +  diagnostic(bool, PrintDTraceDOF, false,                                   \
    24.8 +             "Print the DTrace DOF passed to the system for JSDT probes")   \
    24.9 +                                                                            \
   24.10    product(bool, UseVMInterruptibleIO, true,                                 \
   24.11            "(Unstable, Solaris-specific) Thread interrupt before or with "   \
   24.12            "EINTR for I/O operations results in OS_INTRPT")
    25.1 --- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Apr 16 17:36:29 2008 -0400
    25.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Apr 17 22:18:15 2008 -0400
    25.3 @@ -1748,11 +1748,6 @@
    25.4    // _fingerprints array (it is not safe for concurrent readers and a single
    25.5    // writer: this can be fixed if it becomes a problem).
    25.6  
    25.7 -  // Shouldn't be here if running -Xint
    25.8 -  if (Arguments::mode() == Arguments::_int) {
    25.9 -    ShouldNotReachHere();
   25.10 -  }
   25.11 -
   25.12    // Get the address of the ic_miss handlers before we grab the
   25.13    // AdapterHandlerLibrary_lock. This fixes bug 6236259 which
   25.14    // was caused by the initialization of the stubs happening
   25.15 @@ -1997,6 +1992,64 @@
   25.16    return nm;
   25.17  }
   25.18  
   25.19 +#ifdef HAVE_DTRACE_H
   25.20 +// Create a dtrace nmethod for this method.  The wrapper converts the
   25.21 +// java compiled calling convention to the native convention, makes a dummy call
   25.22 +// (actually nops for the size of the call instruction, which become a trap if
   25.23 +// probe is enabled). The returns to the caller. Since this all looks like a
   25.24 +// leaf no thread transition is needed.
   25.25 +
   25.26 +nmethod *AdapterHandlerLibrary::create_dtrace_nmethod(methodHandle method) {
   25.27 +  ResourceMark rm;
   25.28 +  nmethod* nm = NULL;
   25.29 +
   25.30 +  if (PrintCompilation) {
   25.31 +    ttyLocker ttyl;
   25.32 +    tty->print("---   n%s  ");
   25.33 +    method->print_short_name(tty);
   25.34 +    if (method->is_static()) {
   25.35 +      tty->print(" (static)");
   25.36 +    }
   25.37 +    tty->cr();
   25.38 +  }
   25.39 +
   25.40 +  {
   25.41 +    // perform the work while holding the lock, but perform any printing
   25.42 +    // outside the lock
   25.43 +    MutexLocker mu(AdapterHandlerLibrary_lock);
   25.44 +    // See if somebody beat us to it
   25.45 +    nm = method->code();
   25.46 +    if (nm) {
   25.47 +      return nm;
   25.48 +    }
   25.49 +
   25.50 +    // Improve alignment slightly
   25.51 +    u_char* buf = (u_char*)
   25.52 +        (((intptr_t)_buffer + CodeEntryAlignment-1) & ~(CodeEntryAlignment-1));
   25.53 +    CodeBuffer buffer(buf, AdapterHandlerLibrary_size);
   25.54 +    // Need a few relocation entries
   25.55 +    double locs_buf[20];
   25.56 +    buffer.insts()->initialize_shared_locs(
   25.57 +        (relocInfo*)locs_buf, sizeof(locs_buf) / sizeof(relocInfo));
   25.58 +    MacroAssembler _masm(&buffer);
   25.59 +
   25.60 +    // Generate the compiled-to-native wrapper code
   25.61 +    nm = SharedRuntime::generate_dtrace_nmethod(&_masm, method);
   25.62 +  }
   25.63 +  return nm;
   25.64 +}
   25.65 +
   25.66 +// the dtrace method needs to convert java lang string to utf8 string.
   25.67 +void SharedRuntime::get_utf(oopDesc* src, address dst) {
   25.68 +  typeArrayOop jlsValue  = java_lang_String::value(src);
   25.69 +  int          jlsOffset = java_lang_String::offset(src);
   25.70 +  int          jlsLen    = java_lang_String::length(src);
   25.71 +  jchar*       jlsPos    = (jlsLen == 0) ? NULL :
   25.72 +                                           jlsValue->char_at_addr(jlsOffset);
   25.73 +  (void) UNICODE::as_utf8(jlsPos, jlsLen, (char *)dst, max_dtrace_string_size);
   25.74 +}
   25.75 +#endif // ndef HAVE_DTRACE_H
   25.76 +
   25.77  // -------------------------------------------------------------------------
   25.78  // Java-Java calling convention
   25.79  // (what you use when Java calls Java)
    26.1 --- a/src/share/vm/runtime/sharedRuntime.hpp	Wed Apr 16 17:36:29 2008 -0400
    26.2 +++ b/src/share/vm/runtime/sharedRuntime.hpp	Thu Apr 17 22:18:15 2008 -0400
    26.3 @@ -59,6 +59,10 @@
    26.4  
    26.5  #endif // !PRODUCT
    26.6   public:
    26.7 +
    26.8 +  // max bytes for each dtrace string parameter
    26.9 +  enum { max_dtrace_string_size = 256 };
   26.10 +
   26.11    // The following arithmetic routines are used on platforms that do
   26.12    // not have machine instructions to implement their functionality.
   26.13    // Do not remove these.
   26.14 @@ -258,9 +262,6 @@
   26.15  
   26.16   public:
   26.17  
   26.18 -
   26.19 -  static void create_native_wrapper (JavaThread* thread, methodOop method);
   26.20 -
   26.21    // Read the array of BasicTypes from a Java signature, and compute where
   26.22    // compiled Java code would like to put the results.  Values in reg_lo and
   26.23    // reg_hi refer to 4-byte quantities.  Values less than SharedInfo::stack0 are
   26.24 @@ -354,6 +355,19 @@
   26.25                                            VMRegPair *regs,
   26.26                                            BasicType ret_type );
   26.27  
   26.28 +#ifdef HAVE_DTRACE_H
   26.29 +  // Generate a dtrace wrapper for a given method.  The method takes arguments
   26.30 +  // in the Java compiled code convention, marshals them to the native
   26.31 +  // convention (handlizes oops, etc), transitions to native, makes the call,
   26.32 +  // returns to java state (possibly blocking), unhandlizes any result and
   26.33 +  // returns.
   26.34 +  static nmethod *generate_dtrace_nmethod(MacroAssembler* masm,
   26.35 +                                          methodHandle method);
   26.36 +
   26.37 +  // dtrace support to convert a Java string to utf8
   26.38 +  static void get_utf(oopDesc* src, address dst);
   26.39 +#endif // def HAVE_DTRACE_H
   26.40 +
   26.41    // A compiled caller has just called the interpreter, but compiled code
   26.42    // exists.  Patch the caller so he no longer calls into the interpreter.
   26.43    static void fixup_callers_callsite(methodOopDesc* moop, address ret_pc);
   26.44 @@ -492,42 +506,55 @@
   26.45    address _c2i_unverified_entry;
   26.46  
   26.47   public:
   26.48 +
   26.49 +  // The name we give all buffer blobs
   26.50 +  static const char* name;
   26.51 +
   26.52    AdapterHandlerEntry(address i2c_entry, address c2i_entry, address c2i_unverified_entry):
   26.53      _i2c_entry(i2c_entry),
   26.54      _c2i_entry(c2i_entry),
   26.55      _c2i_unverified_entry(c2i_unverified_entry) {
   26.56    }
   26.57 -  // The name we give all buffer blobs
   26.58 -  static const char* name;
   26.59  
   26.60    address get_i2c_entry()            { return _i2c_entry; }
   26.61    address get_c2i_entry()            { return _c2i_entry; }
   26.62    address get_c2i_unverified_entry() { return _c2i_unverified_entry; }
   26.63 +
   26.64    void relocate(address new_base);
   26.65  #ifndef PRODUCT
   26.66    void print();
   26.67  #endif /* PRODUCT */
   26.68  };
   26.69  
   26.70 -
   26.71  class AdapterHandlerLibrary: public AllStatic {
   26.72   private:
   26.73 +  static u_char                   _buffer[];  // the temporary code buffer
   26.74 +  static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection
   26.75 +  static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers
   26.76    enum {
   26.77      AbstractMethodHandler = 1 // special handler for abstract methods
   26.78    };
   26.79 -  static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection
   26.80 -  static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers
   26.81 -  static u_char                   _buffer[];  // the temporary code buffer
   26.82    static void initialize();
   26.83 -  static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); }
   26.84    static int get_create_adapter_index(methodHandle method);
   26.85 -  static address get_i2c_entry( int index ) { return get_entry(index)->get_i2c_entry(); }
   26.86 -  static address get_c2i_entry( int index ) { return get_entry(index)->get_c2i_entry(); }
   26.87 -  static address get_c2i_unverified_entry( int index ) { return get_entry(index)->get_c2i_unverified_entry(); }
   26.88 +  static address get_i2c_entry( int index ) {
   26.89 +    return get_entry(index)->get_i2c_entry();
   26.90 +  }
   26.91 +  static address get_c2i_entry( int index ) {
   26.92 +    return get_entry(index)->get_c2i_entry();
   26.93 +  }
   26.94 +  static address get_c2i_unverified_entry( int index ) {
   26.95 +    return get_entry(index)->get_c2i_unverified_entry();
   26.96 +  }
   26.97  
   26.98   public:
   26.99 +  static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); }
  26.100    static nmethod* create_native_wrapper(methodHandle method);
  26.101 -  static AdapterHandlerEntry* get_adapter(methodHandle method)  { return get_entry(get_create_adapter_index(method)); }
  26.102 +  static AdapterHandlerEntry* get_adapter(methodHandle method)  {
  26.103 +    return get_entry(get_create_adapter_index(method));
  26.104 +  }
  26.105 +#ifdef HAVE_DTRACE_H
  26.106 +  static nmethod* create_dtrace_nmethod (methodHandle method);
  26.107 +#endif // HAVE_DTRACE_H
  26.108  
  26.109  #ifndef PRODUCT
  26.110    static void print_handler(CodeBlob* b);

mercurial