src/cpu/x86/vm/jniFastGetField_x86_32.cpp

Fri, 16 Aug 2019 16:50:17 +0200

author
eosterlund
date
Fri, 16 Aug 2019 16:50:17 +0200
changeset 9834
bb1da64b0492
parent 9669
32bc598624bd
child 9703
2fdf635bcf28
permissions
-rw-r--r--

8229345: Memory leak due to vtable stubs not being shared on SPARC
Reviewed-by: mdoerr, dholmes, kvn

     1 /*
     2  * Copyright (c) 2004, 2017, 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 "asm/macroAssembler.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 = NULL;
    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
    89   __ clear_jweak_tag(rdx);
    91   __ movptr(rdx, Address(rdx, 0));           // *obj
    92   __ shrptr (rax, 2);                        // offset
    94   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
    95   speculative_load_pclist[count] = __ pc();
    96   switch (type) {
    97     case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break;
    98     case T_BYTE:    __ movsbl (rax, Address(rdx, rax, Address::times_1)); break;
    99     case T_CHAR:    __ movzwl (rax, Address(rdx, rax, Address::times_1)); break;
   100     case T_SHORT:   __ movswl (rax, Address(rdx, rax, Address::times_1)); break;
   101     case T_INT:     __ movl   (rax, Address(rdx, rax, Address::times_1)); break;
   102     default:        ShouldNotReachHere();
   103   }
   105   Address ca1;
   106   if (os::is_MP()) {
   107     __ lea(rdx, counter);
   108     __ xorptr(rdx, rax);
   109     __ xorptr(rdx, rax);
   110     __ cmp32(rcx, Address(rdx, 0));
   111     // ca1 is the same as ca because
   112     // rax, ^ counter_addr ^ rax, = address
   113     // ca1 is data dependent on rax,.
   114   } else {
   115     __ cmp32(rcx, counter);
   116   }
   117   __ jcc (Assembler::notEqual, slow);
   119 #ifndef _WINDOWS
   120   __ ret (0);
   121 #else
   122   // __stdcall calling convention
   123   __ ret (3*wordSize);
   124 #endif
   126   slowcase_entry_pclist[count++] = __ pc();
   127   __ bind (slow);
   128   address slow_case_addr = NULL;
   129   switch (type) {
   130     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
   131     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
   132     case T_CHAR:    slow_case_addr = jni_GetCharField_addr();    break;
   133     case T_SHORT:   slow_case_addr = jni_GetShortField_addr();   break;
   134     case T_INT:     slow_case_addr = jni_GetIntField_addr();
   135   }
   136   // tail call
   137   __ jump (ExternalAddress(slow_case_addr));
   139   __ flush ();
   141 #ifndef _WINDOWS
   142   return fast_entry;
   143 #else
   144   switch (type) {
   145   case T_BOOLEAN: jni_fast_GetBooleanField_fp = (GetBooleanField_t) fast_entry; break;
   146   case T_BYTE:    jni_fast_GetByteField_fp    = (GetByteField_t)    fast_entry; break;
   147   case T_CHAR:    jni_fast_GetCharField_fp    = (GetCharField_t)    fast_entry; break;
   148   case T_SHORT:   jni_fast_GetShortField_fp   = (GetShortField_t)   fast_entry; break;
   149   case T_INT:     jni_fast_GetIntField_fp     = (GetIntField_t)     fast_entry; break;
   150   }
   151   return os::win32::fast_jni_accessor_wrapper(type);
   152 #endif
   153 }
   155 address JNI_FastGetField::generate_fast_get_boolean_field() {
   156   return generate_fast_get_int_field0(T_BOOLEAN);
   157 }
   159 address JNI_FastGetField::generate_fast_get_byte_field() {
   160   return generate_fast_get_int_field0(T_BYTE);
   161 }
   163 address JNI_FastGetField::generate_fast_get_char_field() {
   164   return generate_fast_get_int_field0(T_CHAR);
   165 }
   167 address JNI_FastGetField::generate_fast_get_short_field() {
   168   return generate_fast_get_int_field0(T_SHORT);
   169 }
   171 address JNI_FastGetField::generate_fast_get_int_field() {
   172   return generate_fast_get_int_field0(T_INT);
   173 }
   175 address JNI_FastGetField::generate_fast_get_long_field() {
   176   const char *name = "jni_fast_GetLongField";
   177   ResourceMark rm;
   178   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   179   CodeBuffer cbuf(blob);
   180   MacroAssembler* masm = new MacroAssembler(&cbuf);
   181   address fast_entry = __ pc();
   183   Label slow;
   185   // stack layout:    offset from rsp (in words):
   186   //  old rsi          0
   187   //  return pc        1
   188   //  jni env          2
   189   //  obj              3
   190   //  jfieldID         4
   192   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
   194   __ push  (rsi);
   195   __ mov32 (rcx, counter);
   196   __ testb (rcx, 1);
   197   __ jcc (Assembler::notZero, slow);
   198   if (os::is_MP()) {
   199     __ mov(rax, rcx);
   200     __ andptr(rax, 1);                        // rax, must end up 0
   201     __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize));
   202                                               // obj, notice rax, is 0.
   203                                               // rdx is data dependent on rcx.
   204   } else {
   205     __ movptr(rdx, Address(rsp, 3*wordSize)); // obj
   206   }
   207   __ movptr(rsi, Address(rsp, 4*wordSize));  // jfieldID
   209   __ clear_jweak_tag(rdx);
   211   __ movptr(rdx, Address(rdx, 0));           // *obj
   212   __ shrptr(rsi, 2);                         // offset
   214   assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
   215   speculative_load_pclist[count++] = __ pc();
   216   __ movptr(rax, Address(rdx, rsi, Address::times_1));
   217 #ifndef _LP64
   218   speculative_load_pclist[count] = __ pc();
   219   __ movl(rdx, Address(rdx, rsi, Address::times_1, 4));
   220 #endif // _LP64
   222   if (os::is_MP()) {
   223     __ lea(rsi, counter);
   224     __ xorptr(rsi, rdx);
   225     __ xorptr(rsi, rax);
   226     __ xorptr(rsi, rdx);
   227     __ xorptr(rsi, rax);
   228     __ cmp32(rcx, Address(rsi, 0));
   229     // ca1 is the same as ca because
   230     // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address
   231     // ca1 is data dependent on both rax, and rdx.
   232   } else {
   233     __ cmp32(rcx, counter);
   234   }
   235   __ jcc (Assembler::notEqual, slow);
   237   __ pop (rsi);
   239 #ifndef _WINDOWS
   240   __ ret (0);
   241 #else
   242   // __stdcall calling convention
   243   __ ret (3*wordSize);
   244 #endif
   246   slowcase_entry_pclist[count-1] = __ pc();
   247   slowcase_entry_pclist[count++] = __ pc();
   248   __ bind (slow);
   249   __ pop  (rsi);
   250   address slow_case_addr = jni_GetLongField_addr();;
   251   // tail call
   252   __ jump (ExternalAddress(slow_case_addr));
   254   __ flush ();
   256 #ifndef _WINDOWS
   257   return fast_entry;
   258 #else
   259   jni_fast_GetLongField_fp = (GetLongField_t) fast_entry;
   260   return os::win32::fast_jni_accessor_wrapper(T_LONG);
   261 #endif
   262 }
   264 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
   265   const char *name = NULL;
   266   switch (type) {
   267     case T_FLOAT:  name = "jni_fast_GetFloatField";  break;
   268     case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
   269     default:       ShouldNotReachHere();
   270   }
   271   ResourceMark rm;
   272   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   273   CodeBuffer cbuf(blob);
   274   MacroAssembler* masm = new MacroAssembler(&cbuf);
   275   address fast_entry = __ pc();
   277   Label slow_with_pop, slow;
   279   // stack layout:    offset from rsp (in words):
   280   //  return pc        0
   281   //  jni env          1
   282   //  obj              2
   283   //  jfieldID         3
   285   ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
   287   __ mov32 (rcx, counter);
   288   __ testb (rcx, 1);
   289   __ jcc (Assembler::notZero, slow);
   290   if (os::is_MP()) {
   291     __ mov(rax, rcx);
   292     __ andptr(rax, 1);                        // rax, must end up 0
   293     __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
   294                                               // obj, notice rax, is 0.
   295                                               // rdx is data dependent on rcx.
   296   } else {
   297     __ movptr(rdx, Address(rsp, 2*wordSize)); // obj
   298   }
   299   __ movptr(rax, Address(rsp, 3*wordSize));  // jfieldID
   301   __ clear_jweak_tag(rdx);
   303   __ movptr(rdx, Address(rdx, 0));           // *obj
   304   __ shrptr(rax, 2);                         // offset
   306   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   307   speculative_load_pclist[count] = __ pc();
   308   switch (type) {
   309 #ifndef _LP64
   310     case T_FLOAT:  __ fld_s (Address(rdx, rax, Address::times_1)); break;
   311     case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break;
   312 #else
   313     case T_FLOAT:  __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
   314     case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
   315 #endif // _LP64
   316     default:       ShouldNotReachHere();
   317   }
   319   Address ca1;
   320   if (os::is_MP()) {
   321     __ fst_s (Address(rsp, -4));
   322     __ lea(rdx, counter);
   323     __ movl (rax, Address(rsp, -4));
   324     // garbage hi-order bits on 64bit are harmless.
   325     __ xorptr(rdx, rax);
   326     __ xorptr(rdx, rax);
   327     __ cmp32(rcx, Address(rdx, 0));
   328                                           // rax, ^ counter_addr ^ rax, = address
   329                                           // ca1 is data dependent on the field
   330                                           // access.
   331   } else {
   332     __ cmp32(rcx, counter);
   333   }
   334   __ jcc (Assembler::notEqual, slow_with_pop);
   336 #ifndef _WINDOWS
   337   __ ret (0);
   338 #else
   339   // __stdcall calling convention
   340   __ ret (3*wordSize);
   341 #endif
   343   __ bind (slow_with_pop);
   344   // invalid load. pop FPU stack.
   345   __ fstp_d (0);
   347   slowcase_entry_pclist[count++] = __ pc();
   348   __ bind (slow);
   349   address slow_case_addr = NULL;
   350   switch (type) {
   351     case T_FLOAT:  slow_case_addr = jni_GetFloatField_addr();  break;
   352     case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
   353     default:       ShouldNotReachHere();
   354   }
   355   // tail call
   356   __ jump (ExternalAddress(slow_case_addr));
   358   __ flush ();
   360 #ifndef _WINDOWS
   361   return fast_entry;
   362 #else
   363   switch (type) {
   364   case T_FLOAT:  jni_fast_GetFloatField_fp  = (GetFloatField_t)  fast_entry; break;
   365   case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break;
   366   }
   367   return os::win32::fast_jni_accessor_wrapper(type);
   368 #endif
   369 }
   371 address JNI_FastGetField::generate_fast_get_float_field() {
   372   return generate_fast_get_float_field0(T_FLOAT);
   373 }
   375 address JNI_FastGetField::generate_fast_get_double_field() {
   376   return generate_fast_get_float_field0(T_DOUBLE);
   377 }

mercurial