src/cpu/x86/vm/jniFastGetField_x86_64.cpp

Fri, 13 Mar 2009 11:35:17 -0700

author
twisti
date
Fri, 13 Mar 2009 11:35:17 -0700
changeset 1078
c771b7f43bbf
parent 772
9ee9cf798b59
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6378821: bitCount() should use POPC on SPARC processors and AMD+10h
Summary: bitCount() should use POPC on SPARC processors where POPC is implemented directly in hardware.
Reviewed-by: kvn, never

     1 /*
     2  * Copyright 2004-2008 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_jniFastGetField_x86_64.cpp.incl"
    28 #define __ masm->
    30 #define BUFFER_SIZE 30*wordSize
    32 // Instead of issuing lfence for LoadLoad barrier, we create data dependency
    33 // between loads, which is more efficient than lfence.
    35 // Common register usage:
    36 // rax/xmm0: result
    37 // c_rarg0:    jni env
    38 // c_rarg1:    obj
    39 // c_rarg2:    jfield id
    41 static const Register robj          = r9;
    42 static const Register rcounter      = r10;
    43 static const Register roffset       = r11;
    44 static const Register rcounter_addr = r11;
    46 // Warning: do not use rip relative addressing after the first counter load
    47 // since that may scratch r10!
    49 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
    50   const char *name;
    51   switch (type) {
    52     case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
    53     case T_BYTE:    name = "jni_fast_GetByteField";    break;
    54     case T_CHAR:    name = "jni_fast_GetCharField";    break;
    55     case T_SHORT:   name = "jni_fast_GetShortField";   break;
    56     case T_INT:     name = "jni_fast_GetIntField";     break;
    57     case T_LONG:    name = "jni_fast_GetLongField";    break;
    58     default:        ShouldNotReachHere();
    59   }
    60   ResourceMark rm;
    61   BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE);
    62   address fast_entry = b->instructions_begin();
    63   CodeBuffer cbuf(fast_entry, b->instructions_size());
    64   MacroAssembler* masm = new MacroAssembler(&cbuf);
    66   Label slow;
    68   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
    69   __ mov32 (rcounter, counter);
    70   __ mov   (robj, c_rarg1);
    71   __ testb (rcounter, 1);
    72   __ jcc (Assembler::notZero, slow);
    73   if (os::is_MP()) {
    74     __ xorptr(robj, rcounter);
    75     __ xorptr(robj, rcounter);                   // obj, since
    76                                                 // robj ^ rcounter ^ rcounter == robj
    77                                                 // robj is data dependent on rcounter.
    78   }
    79   __ movptr(robj, Address(robj, 0));             // *obj
    80   __ mov   (roffset, c_rarg2);
    81   __ shrptr(roffset, 2);                         // offset
    83   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
    84   speculative_load_pclist[count] = __ pc();
    85   switch (type) {
    86     case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break;
    87     case T_BYTE:    __ movsbl (rax, Address(robj, roffset, Address::times_1)); break;
    88     case T_CHAR:    __ movzwl (rax, Address(robj, roffset, Address::times_1)); break;
    89     case T_SHORT:   __ movswl (rax, Address(robj, roffset, Address::times_1)); break;
    90     case T_INT:     __ movl   (rax, Address(robj, roffset, Address::times_1)); break;
    91     case T_LONG:    __ movq   (rax, Address(robj, roffset, Address::times_1)); break;
    92     default:        ShouldNotReachHere();
    93   }
    95   if (os::is_MP()) {
    96     __ lea(rcounter_addr, counter);
    97     // ca is data dependent on rax.
    98     __ xorptr(rcounter_addr, rax);
    99     __ xorptr(rcounter_addr, rax);
   100     __ cmpl (rcounter, Address(rcounter_addr, 0));
   101   } else {
   102     __ cmp32 (rcounter, counter);
   103   }
   104   __ jcc (Assembler::notEqual, slow);
   106   __ ret (0);
   108   slowcase_entry_pclist[count++] = __ pc();
   109   __ bind (slow);
   110   address slow_case_addr;
   111   switch (type) {
   112     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
   113     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
   114     case T_CHAR:    slow_case_addr = jni_GetCharField_addr();    break;
   115     case T_SHORT:   slow_case_addr = jni_GetShortField_addr();   break;
   116     case T_INT:     slow_case_addr = jni_GetIntField_addr();     break;
   117     case T_LONG:    slow_case_addr = jni_GetLongField_addr();
   118   }
   119   // tail call
   120   __ jump (ExternalAddress(slow_case_addr));
   122   __ flush ();
   124   return fast_entry;
   125 }
   127 address JNI_FastGetField::generate_fast_get_boolean_field() {
   128   return generate_fast_get_int_field0(T_BOOLEAN);
   129 }
   131 address JNI_FastGetField::generate_fast_get_byte_field() {
   132   return generate_fast_get_int_field0(T_BYTE);
   133 }
   135 address JNI_FastGetField::generate_fast_get_char_field() {
   136   return generate_fast_get_int_field0(T_CHAR);
   137 }
   139 address JNI_FastGetField::generate_fast_get_short_field() {
   140   return generate_fast_get_int_field0(T_SHORT);
   141 }
   143 address JNI_FastGetField::generate_fast_get_int_field() {
   144   return generate_fast_get_int_field0(T_INT);
   145 }
   147 address JNI_FastGetField::generate_fast_get_long_field() {
   148   return generate_fast_get_int_field0(T_LONG);
   149 }
   151 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
   152   const char *name;
   153   switch (type) {
   154     case T_FLOAT:     name = "jni_fast_GetFloatField";     break;
   155     case T_DOUBLE:    name = "jni_fast_GetDoubleField";    break;
   156     default:          ShouldNotReachHere();
   157   }
   158   ResourceMark rm;
   159   BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE);
   160   address fast_entry = b->instructions_begin();
   161   CodeBuffer cbuf(fast_entry, b->instructions_size());
   162   MacroAssembler* masm = new MacroAssembler(&cbuf);
   164   Label slow;
   166   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
   167   __ mov32 (rcounter, counter);
   168   __ mov   (robj, c_rarg1);
   169   __ testb (rcounter, 1);
   170   __ jcc (Assembler::notZero, slow);
   171   if (os::is_MP()) {
   172     __ xorptr(robj, rcounter);
   173     __ xorptr(robj, rcounter);                   // obj, since
   174                                                 // robj ^ rcounter ^ rcounter == robj
   175                                                 // robj is data dependent on rcounter.
   176   }
   177   __ movptr(robj, Address(robj, 0));             // *obj
   178   __ mov   (roffset, c_rarg2);
   179   __ shrptr(roffset, 2);                         // offset
   181   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   182   speculative_load_pclist[count] = __ pc();
   183   switch (type) {
   184     case T_FLOAT:  __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
   185     case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
   186     default:        ShouldNotReachHere();
   187   }
   189   if (os::is_MP()) {
   190     __ lea(rcounter_addr, counter);
   191     __ movdq (rax, xmm0);
   192     // counter address is data dependent on xmm0.
   193     __ xorptr(rcounter_addr, rax);
   194     __ xorptr(rcounter_addr, rax);
   195     __ cmpl (rcounter, Address(rcounter_addr, 0));
   196   } else {
   197     __ cmp32 (rcounter, counter);
   198   }
   199   __ jcc (Assembler::notEqual, slow);
   201   __ ret (0);
   203   slowcase_entry_pclist[count++] = __ pc();
   204   __ bind (slow);
   205   address slow_case_addr;
   206   switch (type) {
   207     case T_FLOAT:     slow_case_addr = jni_GetFloatField_addr();  break;
   208     case T_DOUBLE:    slow_case_addr = jni_GetDoubleField_addr();
   209   }
   210   // tail call
   211   __ jump (ExternalAddress(slow_case_addr));
   213   __ flush ();
   215   return fast_entry;
   216 }
   218 address JNI_FastGetField::generate_fast_get_float_field() {
   219   return generate_fast_get_float_field0(T_FLOAT);
   220 }
   222 address JNI_FastGetField::generate_fast_get_double_field() {
   223   return generate_fast_get_float_field0(T_DOUBLE);
   224 }

mercurial