src/cpu/x86/vm/jniFastGetField_x86_32.cpp

Thu, 03 Nov 2011 04:12:49 -0700

author
twisti
date
Thu, 03 Nov 2011 04:12:49 -0700
changeset 3252
448691f285a5
parent 2314
f95d63e2154a
child 4318
cd3d6a6b95d9
permissions
-rw-r--r--

7106944: assert(_pc == *pc_addr) failed may be too strong
Reviewed-by: kvn, never

     1 /*
     2  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "assembler_x86.inline.hpp"
    27 #include "memory/resourceArea.hpp"
    28 #include "prims/jniFastGetField.hpp"
    29 #include "prims/jvm_misc.hpp"
    30 #include "runtime/safepoint.hpp"
    32 #define __ masm->
    34 #define BUFFER_SIZE 30
    36 #ifdef _WINDOWS
    37 GetBooleanField_t JNI_FastGetField::jni_fast_GetBooleanField_fp;
    38 GetByteField_t    JNI_FastGetField::jni_fast_GetByteField_fp;
    39 GetCharField_t    JNI_FastGetField::jni_fast_GetCharField_fp;
    40 GetShortField_t   JNI_FastGetField::jni_fast_GetShortField_fp;
    41 GetIntField_t     JNI_FastGetField::jni_fast_GetIntField_fp;
    42 GetLongField_t    JNI_FastGetField::jni_fast_GetLongField_fp;
    43 GetFloatField_t   JNI_FastGetField::jni_fast_GetFloatField_fp;
    44 GetDoubleField_t  JNI_FastGetField::jni_fast_GetDoubleField_fp;
    45 #endif
    47 // Instead of issuing lfence for LoadLoad barrier, we create data dependency
    48 // between loads, which is much more efficient than lfence.
    50 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
    51   const char *name;
    52   switch (type) {
    53     case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
    54     case T_BYTE:    name = "jni_fast_GetByteField";    break;
    55     case T_CHAR:    name = "jni_fast_GetCharField";    break;
    56     case T_SHORT:   name = "jni_fast_GetShortField";   break;
    57     case T_INT:     name = "jni_fast_GetIntField";     break;
    58     default:        ShouldNotReachHere();
    59   }
    60   ResourceMark rm;
    61   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
    62   CodeBuffer cbuf(blob);
    63   MacroAssembler* masm = new MacroAssembler(&cbuf);
    64   address fast_entry = __ pc();
    66   Label slow;
    68   // stack layout:    offset from rsp (in words):
    69   //  return pc        0
    70   //  jni env          1
    71   //  obj              2
    72   //  jfieldID         3
    74   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
    75   __ mov32 (rcx, counter);
    76   __ testb (rcx, 1);
    77   __ jcc (Assembler::notZero, slow);
    78   if (os::is_MP()) {
    79     __ mov(rax, rcx);
    80     __ andptr(rax, 1);                         // rax, must end up 0
    81     __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
    82                                               // obj, notice rax, is 0.
    83                                               // rdx is data dependent on rcx.
    84   } else {
    85     __ movptr (rdx, Address(rsp, 2*wordSize));  // obj
    86   }
    87   __ movptr(rax, Address(rsp, 3*wordSize));  // jfieldID
    88   __ movptr(rdx, Address(rdx, 0));           // *obj
    89   __ shrptr (rax, 2);                         // offset
    91   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
    92   speculative_load_pclist[count] = __ pc();
    93   switch (type) {
    94     case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break;
    95     case T_BYTE:    __ movsbl (rax, Address(rdx, rax, Address::times_1)); break;
    96     case T_CHAR:    __ movzwl (rax, Address(rdx, rax, Address::times_1)); break;
    97     case T_SHORT:   __ movswl (rax, Address(rdx, rax, Address::times_1)); break;
    98     case T_INT:     __ movl   (rax, Address(rdx, rax, Address::times_1)); break;
    99     default:        ShouldNotReachHere();
   100   }
   102   Address ca1;
   103   if (os::is_MP()) {
   104     __ lea(rdx, counter);
   105     __ xorptr(rdx, rax);
   106     __ xorptr(rdx, rax);
   107     __ cmp32(rcx, Address(rdx, 0));
   108     // ca1 is the same as ca because
   109     // rax, ^ counter_addr ^ rax, = address
   110     // ca1 is data dependent on rax,.
   111   } else {
   112     __ cmp32(rcx, counter);
   113   }
   114   __ jcc (Assembler::notEqual, slow);
   116 #ifndef _WINDOWS
   117   __ ret (0);
   118 #else
   119   // __stdcall calling convention
   120   __ ret (3*wordSize);
   121 #endif
   123   slowcase_entry_pclist[count++] = __ pc();
   124   __ bind (slow);
   125   address slow_case_addr;
   126   switch (type) {
   127     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
   128     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
   129     case T_CHAR:    slow_case_addr = jni_GetCharField_addr();    break;
   130     case T_SHORT:   slow_case_addr = jni_GetShortField_addr();   break;
   131     case T_INT:     slow_case_addr = jni_GetIntField_addr();
   132   }
   133   // tail call
   134   __ jump (ExternalAddress(slow_case_addr));
   136   __ flush ();
   138 #ifndef _WINDOWS
   139   return fast_entry;
   140 #else
   141   switch (type) {
   142   case T_BOOLEAN: jni_fast_GetBooleanField_fp = (GetBooleanField_t) fast_entry; break;
   143   case T_BYTE:    jni_fast_GetByteField_fp    = (GetByteField_t)    fast_entry; break;
   144   case T_CHAR:    jni_fast_GetCharField_fp    = (GetCharField_t)    fast_entry; break;
   145   case T_SHORT:   jni_fast_GetShortField_fp   = (GetShortField_t)   fast_entry; break;
   146   case T_INT:     jni_fast_GetIntField_fp     = (GetIntField_t)     fast_entry; break;
   147   }
   148   return os::win32::fast_jni_accessor_wrapper(type);
   149 #endif
   150 }
   152 address JNI_FastGetField::generate_fast_get_boolean_field() {
   153   return generate_fast_get_int_field0(T_BOOLEAN);
   154 }
   156 address JNI_FastGetField::generate_fast_get_byte_field() {
   157   return generate_fast_get_int_field0(T_BYTE);
   158 }
   160 address JNI_FastGetField::generate_fast_get_char_field() {
   161   return generate_fast_get_int_field0(T_CHAR);
   162 }
   164 address JNI_FastGetField::generate_fast_get_short_field() {
   165   return generate_fast_get_int_field0(T_SHORT);
   166 }
   168 address JNI_FastGetField::generate_fast_get_int_field() {
   169   return generate_fast_get_int_field0(T_INT);
   170 }
   172 address JNI_FastGetField::generate_fast_get_long_field() {
   173   const char *name = "jni_fast_GetLongField";
   174   ResourceMark rm;
   175   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   176   CodeBuffer cbuf(blob);
   177   MacroAssembler* masm = new MacroAssembler(&cbuf);
   178   address fast_entry = __ pc();
   180   Label slow;
   182   // stack layout:    offset from rsp (in words):
   183   //  old rsi          0
   184   //  return pc        1
   185   //  jni env          2
   186   //  obj              3
   187   //  jfieldID         4
   189   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
   191   __ push  (rsi);
   192   __ mov32 (rcx, counter);
   193   __ testb (rcx, 1);
   194   __ jcc (Assembler::notZero, slow);
   195   if (os::is_MP()) {
   196     __ mov(rax, rcx);
   197     __ andptr(rax, 1);                         // rax, must end up 0
   198     __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize));
   199                                               // obj, notice rax, is 0.
   200                                               // rdx is data dependent on rcx.
   201   } else {
   202     __ movptr(rdx, Address(rsp, 3*wordSize));  // obj
   203   }
   204   __ movptr(rsi, Address(rsp, 4*wordSize));  // jfieldID
   205   __ movptr(rdx, Address(rdx, 0));           // *obj
   206   __ shrptr(rsi, 2);                         // offset
   208   assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
   209   speculative_load_pclist[count++] = __ pc();
   210   __ movptr(rax, Address(rdx, rsi, Address::times_1));
   211 #ifndef _LP64
   212   speculative_load_pclist[count] = __ pc();
   213   __ movl(rdx, Address(rdx, rsi, Address::times_1, 4));
   214 #endif // _LP64
   216   if (os::is_MP()) {
   217     __ lea(rsi, counter);
   218     __ xorptr(rsi, rdx);
   219     __ xorptr(rsi, rax);
   220     __ xorptr(rsi, rdx);
   221     __ xorptr(rsi, rax);
   222     __ cmp32(rcx, Address(rsi, 0));
   223     // ca1 is the same as ca because
   224     // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address
   225     // ca1 is data dependent on both rax, and rdx.
   226   } else {
   227     __ cmp32(rcx, counter);
   228   }
   229   __ jcc (Assembler::notEqual, slow);
   231   __ pop (rsi);
   233 #ifndef _WINDOWS
   234   __ ret (0);
   235 #else
   236   // __stdcall calling convention
   237   __ ret (3*wordSize);
   238 #endif
   240   slowcase_entry_pclist[count-1] = __ pc();
   241   slowcase_entry_pclist[count++] = __ pc();
   242   __ bind (slow);
   243   __ pop  (rsi);
   244   address slow_case_addr = jni_GetLongField_addr();;
   245   // tail call
   246   __ jump (ExternalAddress(slow_case_addr));
   248   __ flush ();
   250 #ifndef _WINDOWS
   251   return fast_entry;
   252 #else
   253   jni_fast_GetLongField_fp = (GetLongField_t) fast_entry;
   254   return os::win32::fast_jni_accessor_wrapper(T_LONG);
   255 #endif
   256 }
   258 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
   259   const char *name;
   260   switch (type) {
   261     case T_FLOAT:  name = "jni_fast_GetFloatField";  break;
   262     case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
   263     default:       ShouldNotReachHere();
   264   }
   265   ResourceMark rm;
   266   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   267   CodeBuffer cbuf(blob);
   268   MacroAssembler* masm = new MacroAssembler(&cbuf);
   269   address fast_entry = __ pc();
   271   Label slow_with_pop, slow;
   273   // stack layout:    offset from rsp (in words):
   274   //  return pc        0
   275   //  jni env          1
   276   //  obj              2
   277   //  jfieldID         3
   279   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
   281   __ mov32 (rcx, counter);
   282   __ testb (rcx, 1);
   283   __ jcc (Assembler::notZero, slow);
   284   if (os::is_MP()) {
   285     __ mov(rax, rcx);
   286     __ andptr(rax, 1);                         // rax, must end up 0
   287     __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
   288                                               // obj, notice rax, is 0.
   289                                               // rdx is data dependent on rcx.
   290   } else {
   291     __ movptr(rdx, Address(rsp, 2*wordSize)); // obj
   292   }
   293   __ movptr(rax, Address(rsp, 3*wordSize));  // jfieldID
   294   __ movptr(rdx, Address(rdx, 0));           // *obj
   295   __ shrptr(rax, 2);                         // offset
   297   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   298   speculative_load_pclist[count] = __ pc();
   299   switch (type) {
   300 #ifndef _LP64
   301     case T_FLOAT:  __ fld_s (Address(rdx, rax, Address::times_1)); break;
   302     case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break;
   303 #else
   304     case T_FLOAT:  __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
   305     case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
   306 #endif // _LP64
   307     default:       ShouldNotReachHere();
   308   }
   310   Address ca1;
   311   if (os::is_MP()) {
   312     __ fst_s (Address(rsp, -4));
   313     __ lea(rdx, counter);
   314     __ movl (rax, Address(rsp, -4));
   315     // garbage hi-order bits on 64bit are harmless.
   316     __ xorptr(rdx, rax);
   317     __ xorptr(rdx, rax);
   318     __ cmp32(rcx, Address(rdx, 0));
   319                                           // rax, ^ counter_addr ^ rax, = address
   320                                           // ca1 is data dependent on the field
   321                                           // access.
   322   } else {
   323     __ cmp32(rcx, counter);
   324   }
   325   __ jcc (Assembler::notEqual, slow_with_pop);
   327 #ifndef _WINDOWS
   328   __ ret (0);
   329 #else
   330   // __stdcall calling convention
   331   __ ret (3*wordSize);
   332 #endif
   334   __ bind (slow_with_pop);
   335   // invalid load. pop FPU stack.
   336   __ fstp_d (0);
   338   slowcase_entry_pclist[count++] = __ pc();
   339   __ bind (slow);
   340   address slow_case_addr;
   341   switch (type) {
   342     case T_FLOAT:  slow_case_addr = jni_GetFloatField_addr();  break;
   343     case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
   344     default:       ShouldNotReachHere();
   345   }
   346   // tail call
   347   __ jump (ExternalAddress(slow_case_addr));
   349   __ flush ();
   351 #ifndef _WINDOWS
   352   return fast_entry;
   353 #else
   354   switch (type) {
   355   case T_FLOAT:  jni_fast_GetFloatField_fp  = (GetFloatField_t)  fast_entry; break;
   356   case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break;
   357   }
   358   return os::win32::fast_jni_accessor_wrapper(type);
   359 #endif
   360 }
   362 address JNI_FastGetField::generate_fast_get_float_field() {
   363   return generate_fast_get_float_field0(T_FLOAT);
   364 }
   366 address JNI_FastGetField::generate_fast_get_double_field() {
   367   return generate_fast_get_float_field0(T_DOUBLE);
   368 }

mercurial