hotspot/src/share/vm/shark/sharkNativeWrapper.cpp
changeset 6187 4fa7845f7c14
child 7397 5b173b4ca846
equal deleted inserted replaced
6186:7eef4cda471c 6187:4fa7845f7c14
       
     1 /*
       
     2  * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
       
     3  * Copyright 2009, 2010 Red Hat, Inc.
       
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     5  *
       
     6  * This code is free software; you can redistribute it and/or modify it
       
     7  * under the terms of the GNU General Public License version 2 only, as
       
     8  * published by the Free Software Foundation.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  *
       
    24  */
       
    25 
       
    26 #include "incls/_precompiled.incl"
       
    27 #include "incls/_sharkNativeWrapper.cpp.incl"
       
    28 
       
    29 using namespace llvm;
       
    30 
       
    31 void SharkNativeWrapper::initialize(const char *name) {
       
    32   // Create the function
       
    33   _function = Function::Create(
       
    34     SharkType::entry_point_type(),
       
    35     GlobalVariable::InternalLinkage,
       
    36     name);
       
    37 
       
    38   // Get our arguments
       
    39   Function::arg_iterator ai = function()->arg_begin();
       
    40   Argument *method = ai++;
       
    41   method->setName("method");
       
    42   Argument *base_pc = ai++;
       
    43   base_pc->setName("base_pc");
       
    44   code_buffer()->set_base_pc(base_pc);
       
    45   Argument *thread = ai++;
       
    46   thread->setName("thread");
       
    47   set_thread(thread);
       
    48 
       
    49   // Create and push our stack frame
       
    50   builder()->SetInsertPoint(CreateBlock());
       
    51   _stack = SharkStack::CreateBuildAndPushFrame(this, method);
       
    52   NOT_PRODUCT(method = NULL);
       
    53 
       
    54   // Create the oopmap.  We use the one oopmap for every call site in
       
    55   // the wrapper, which results in the odd mild inefficiency but is a
       
    56   // damn sight easier to code.
       
    57   OopMap *oopmap = new OopMap(
       
    58     SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()),
       
    59     SharkStack::oopmap_slot_munge(arg_size()));
       
    60   oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset()));
       
    61 
       
    62   // Set up the oop_tmp slot if required:
       
    63   //  - For static methods we use it to handlize the class argument
       
    64   //    for the call, and to protect the same during slow path locks
       
    65   //    (if synchronized).
       
    66   //  - For methods returning oops, we use it to protect the return
       
    67   //    value across safepoints or slow path unlocking.
       
    68   if (is_static() || is_returning_oop()) {
       
    69     _oop_tmp_slot = stack()->slot_addr(
       
    70       stack()->oop_tmp_slot_offset(),
       
    71       SharkType::oop_type(),
       
    72       "oop_tmp_slot");
       
    73 
       
    74     oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
       
    75   }
       
    76 
       
    77   // Set up the monitor slot, for synchronized methods
       
    78   if (is_synchronized()) {
       
    79     Unimplemented();
       
    80     _lock_slot_offset = 23;
       
    81   }
       
    82 
       
    83   // Start building the argument list
       
    84   std::vector<const Type*> param_types;
       
    85   std::vector<Value*> param_values;
       
    86   const PointerType *box_type = PointerType::getUnqual(SharkType::oop_type());
       
    87 
       
    88   // First argument is the JNIEnv
       
    89   param_types.push_back(SharkType::jniEnv_type());
       
    90   param_values.push_back(
       
    91     builder()->CreateAddressOfStructEntry(
       
    92       thread,
       
    93       JavaThread::jni_environment_offset(),
       
    94       SharkType::jniEnv_type(),
       
    95       "jni_environment"));
       
    96 
       
    97   // For static methods, the second argument is the class
       
    98   if (is_static()) {
       
    99     builder()->CreateStore(
       
   100       builder()->CreateInlineOop(
       
   101         JNIHandles::make_local(
       
   102           target()->method_holder()->klass_part()->java_mirror())),
       
   103       oop_tmp_slot());
       
   104 
       
   105     param_types.push_back(box_type);
       
   106     param_values.push_back(oop_tmp_slot());
       
   107 
       
   108     _receiver_slot_offset = stack()->oop_tmp_slot_offset();
       
   109   }
       
   110   else if (is_returning_oop()) {
       
   111     // The oop_tmp slot is registered in the oopmap,
       
   112     // so we need to clear it.  This is one of the
       
   113     // mild inefficiencies I mentioned earlier.
       
   114     builder()->CreateStore(LLVMValue::null(), oop_tmp_slot());
       
   115   }
       
   116 
       
   117   // Parse the arguments
       
   118   for (int i = 0; i < arg_size(); i++) {
       
   119     int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i;
       
   120     int adjusted_offset = slot_offset;
       
   121     BasicBlock *null, *not_null, *merge;
       
   122     Value *box;
       
   123     PHINode *phi;
       
   124 
       
   125     switch (arg_type(i)) {
       
   126     case T_VOID:
       
   127       break;
       
   128 
       
   129     case T_OBJECT:
       
   130     case T_ARRAY:
       
   131       null     = CreateBlock("null");
       
   132       not_null = CreateBlock("not_null");
       
   133       merge    = CreateBlock("merge");
       
   134 
       
   135       box = stack()->slot_addr(slot_offset, SharkType::oop_type());
       
   136       builder()->CreateCondBr(
       
   137         builder()->CreateICmp(
       
   138           ICmpInst::ICMP_EQ,
       
   139           builder()->CreateLoad(box),
       
   140           LLVMValue::null()),
       
   141         null, not_null);
       
   142 
       
   143       builder()->SetInsertPoint(null);
       
   144       builder()->CreateBr(merge);
       
   145 
       
   146       builder()->SetInsertPoint(not_null);
       
   147       builder()->CreateBr(merge);
       
   148 
       
   149       builder()->SetInsertPoint(merge);
       
   150       phi = builder()->CreatePHI(box_type, "boxed_object");
       
   151       phi->addIncoming(ConstantPointerNull::get(box_type), null);
       
   152       phi->addIncoming(box, not_null);
       
   153       box = phi;
       
   154 
       
   155       param_types.push_back(box_type);
       
   156       param_values.push_back(box);
       
   157 
       
   158       oopmap->set_oop(SharkStack::slot2reg(slot_offset));
       
   159 
       
   160       if (i == 0 && !is_static())
       
   161         _receiver_slot_offset = slot_offset;
       
   162 
       
   163       break;
       
   164 
       
   165     case T_LONG:
       
   166     case T_DOUBLE:
       
   167       adjusted_offset--;
       
   168       // fall through
       
   169 
       
   170     default:
       
   171       const Type *param_type = SharkType::to_stackType(arg_type(i));
       
   172 
       
   173       param_types.push_back(param_type);
       
   174       param_values.push_back(
       
   175         builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
       
   176     }
       
   177   }
       
   178 
       
   179   // The oopmap is now complete, and everything is written
       
   180   // into the frame except the PC.
       
   181   int pc_offset = code_buffer()->create_unique_offset();
       
   182 
       
   183   _oop_maps = new OopMapSet();
       
   184   oop_maps()->add_gc_map(pc_offset, oopmap);
       
   185 
       
   186   builder()->CreateStore(
       
   187     builder()->code_buffer_address(pc_offset),
       
   188     stack()->slot_addr(stack()->pc_slot_offset()));
       
   189 
       
   190   // Set up the Java frame anchor
       
   191   stack()->CreateSetLastJavaFrame();
       
   192 
       
   193   // Lock if necessary
       
   194   if (is_synchronized())
       
   195     Unimplemented();
       
   196 
       
   197   // Change the thread state to _thread_in_native
       
   198   CreateSetThreadState(_thread_in_native);
       
   199 
       
   200   // Make the call
       
   201   BasicType result_type = target()->result_type();
       
   202   const Type* return_type;
       
   203   if (result_type == T_VOID)
       
   204     return_type = SharkType::void_type();
       
   205   else if (is_returning_oop())
       
   206     return_type = box_type;
       
   207   else
       
   208     return_type = SharkType::to_arrayType(result_type);
       
   209   Value* native_function = builder()->CreateIntToPtr(
       
   210      LLVMValue::intptr_constant((intptr_t) target()->native_function()),
       
   211      PointerType::getUnqual(
       
   212        FunctionType::get(return_type, param_types, false)));
       
   213   Value *result = builder()->CreateCall(
       
   214     native_function, param_values.begin(), param_values.end());
       
   215 
       
   216   // Start the transition back to _thread_in_Java
       
   217   CreateSetThreadState(_thread_in_native_trans);
       
   218 
       
   219   // Make sure new state is visible in the GC thread
       
   220   if (os::is_MP()) {
       
   221     if (UseMembar)
       
   222       builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
       
   223     else
       
   224       CreateWriteMemorySerializePage();
       
   225   }
       
   226 
       
   227   // Handle safepoint operations, pending suspend requests,
       
   228   // and pending asynchronous exceptions.
       
   229   BasicBlock *check_thread = CreateBlock("check_thread");
       
   230   BasicBlock *do_safepoint = CreateBlock("do_safepoint");
       
   231   BasicBlock *safepointed  = CreateBlock("safepointed");
       
   232 
       
   233   Value *global_state = builder()->CreateLoad(
       
   234     builder()->CreateIntToPtr(
       
   235       LLVMValue::intptr_constant(
       
   236         (intptr_t) SafepointSynchronize::address_of_state()),
       
   237       PointerType::getUnqual(SharkType::jint_type())),
       
   238     "global_state");
       
   239 
       
   240   builder()->CreateCondBr(
       
   241     builder()->CreateICmpNE(
       
   242       global_state,
       
   243       LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
       
   244     do_safepoint, check_thread);
       
   245 
       
   246   builder()->SetInsertPoint(check_thread);
       
   247   Value *thread_state = builder()->CreateValueOfStructEntry(
       
   248     thread,
       
   249     JavaThread::suspend_flags_offset(),
       
   250     SharkType::jint_type(),
       
   251     "thread_state");
       
   252 
       
   253   builder()->CreateCondBr(
       
   254     builder()->CreateICmpNE(
       
   255       thread_state,
       
   256       LLVMValue::jint_constant(0)),
       
   257     do_safepoint, safepointed);
       
   258 
       
   259   builder()->SetInsertPoint(do_safepoint);
       
   260   builder()->CreateCall(
       
   261     builder()->check_special_condition_for_native_trans(), thread);
       
   262   builder()->CreateBr(safepointed);
       
   263 
       
   264   // Finally we can change the thread state to _thread_in_Java
       
   265   builder()->SetInsertPoint(safepointed);
       
   266   CreateSetThreadState(_thread_in_Java);
       
   267 
       
   268   // Clear the frame anchor
       
   269   stack()->CreateResetLastJavaFrame();
       
   270 
       
   271   // If there is a pending exception then we can just unwind and
       
   272   // return.  It seems totally wrong that unlocking is skipped here
       
   273   // but apparently the template interpreter does this so we do too.
       
   274   BasicBlock *exception    = CreateBlock("exception");
       
   275   BasicBlock *no_exception = CreateBlock("no_exception");
       
   276 
       
   277   builder()->CreateCondBr(
       
   278     builder()->CreateICmpEQ(
       
   279       CreateLoadPendingException(),
       
   280       LLVMValue::null()),
       
   281     no_exception, exception);
       
   282 
       
   283   builder()->SetInsertPoint(exception);
       
   284   CreateResetHandleBlock();
       
   285   stack()->CreatePopFrame(0);
       
   286   builder()->CreateRet(LLVMValue::jint_constant(0));
       
   287 
       
   288   builder()->SetInsertPoint(no_exception);
       
   289 
       
   290   // If the result was an oop then unbox it before
       
   291   // releasing the handle it might be protected by
       
   292   if (is_returning_oop()) {
       
   293     BasicBlock *null     = builder()->GetInsertBlock();
       
   294     BasicBlock *not_null = CreateBlock("not_null");
       
   295     BasicBlock *merge    = CreateBlock("merge");
       
   296 
       
   297     builder()->CreateCondBr(
       
   298       builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
       
   299       not_null, merge);
       
   300 
       
   301     builder()->SetInsertPoint(not_null);
       
   302     Value *unboxed_result = builder()->CreateLoad(result);
       
   303     builder()->CreateBr(merge);
       
   304 
       
   305     builder()->SetInsertPoint(merge);
       
   306     PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "result");
       
   307     phi->addIncoming(LLVMValue::null(), null);
       
   308     phi->addIncoming(unboxed_result, not_null);
       
   309     result = phi;
       
   310   }
       
   311 
       
   312   // Reset handle block
       
   313   CreateResetHandleBlock();
       
   314 
       
   315   // Unlock if necessary.
       
   316   if (is_synchronized())
       
   317     Unimplemented();
       
   318 
       
   319   // Unwind and return
       
   320   Value *result_addr = stack()->CreatePopFrame(type2size[result_type]);
       
   321   if (result_type != T_VOID) {
       
   322     bool needs_cast = false;
       
   323     bool is_signed = false;
       
   324     switch (result_type) {
       
   325     case T_BOOLEAN:
       
   326       result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0));
       
   327       needs_cast = true;
       
   328       break;
       
   329 
       
   330     case T_CHAR:
       
   331       needs_cast = true;
       
   332       break;
       
   333 
       
   334     case T_BYTE:
       
   335     case T_SHORT:
       
   336       needs_cast = true;
       
   337       is_signed = true;
       
   338       break;
       
   339     }
       
   340     if (needs_cast) {
       
   341       result = builder()->CreateIntCast(
       
   342         result, SharkType::to_stackType(result_type), is_signed);
       
   343     }
       
   344 
       
   345     builder()->CreateStore(
       
   346       result,
       
   347       builder()->CreateIntToPtr(
       
   348         result_addr,
       
   349         PointerType::getUnqual(SharkType::to_stackType(result_type))));
       
   350   }
       
   351   builder()->CreateRet(LLVMValue::jint_constant(0));
       
   352 }