src/share/vm/shark/sharkNativeWrapper.cpp

Wed, 11 Aug 2010 05:51:21 -0700

author
twisti
date
Wed, 11 Aug 2010 05:51:21 -0700
changeset 2047
d2ede61b7a12
child 2314
f95d63e2154a
permissions
-rw-r--r--

6976186: integrate Shark HotSpot changes
Summary: Shark is a JIT compiler for Zero that uses the LLVM compiler infrastructure.
Reviewed-by: kvn, twisti
Contributed-by: Gary Benson <gbenson@redhat.com>

     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  */
    26 #include "incls/_precompiled.incl"
    27 #include "incls/_sharkNativeWrapper.cpp.incl"
    29 using namespace llvm;
    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);
    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);
    49   // Create and push our stack frame
    50   builder()->SetInsertPoint(CreateBlock());
    51   _stack = SharkStack::CreateBuildAndPushFrame(this, method);
    52   NOT_PRODUCT(method = NULL);
    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()));
    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");
    74     oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset()));
    75   }
    77   // Set up the monitor slot, for synchronized methods
    78   if (is_synchronized()) {
    79     Unimplemented();
    80     _lock_slot_offset = 23;
    81   }
    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());
    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"));
    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());
   105     param_types.push_back(box_type);
   106     param_values.push_back(oop_tmp_slot());
   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   }
   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;
   125     switch (arg_type(i)) {
   126     case T_VOID:
   127       break;
   129     case T_OBJECT:
   130     case T_ARRAY:
   131       null     = CreateBlock("null");
   132       not_null = CreateBlock("not_null");
   133       merge    = CreateBlock("merge");
   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);
   143       builder()->SetInsertPoint(null);
   144       builder()->CreateBr(merge);
   146       builder()->SetInsertPoint(not_null);
   147       builder()->CreateBr(merge);
   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;
   155       param_types.push_back(box_type);
   156       param_values.push_back(box);
   158       oopmap->set_oop(SharkStack::slot2reg(slot_offset));
   160       if (i == 0 && !is_static())
   161         _receiver_slot_offset = slot_offset;
   163       break;
   165     case T_LONG:
   166     case T_DOUBLE:
   167       adjusted_offset--;
   168       // fall through
   170     default:
   171       const Type *param_type = SharkType::to_stackType(arg_type(i));
   173       param_types.push_back(param_type);
   174       param_values.push_back(
   175         builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type)));
   176     }
   177   }
   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();
   183   _oop_maps = new OopMapSet();
   184   oop_maps()->add_gc_map(pc_offset, oopmap);
   186   builder()->CreateStore(
   187     builder()->code_buffer_address(pc_offset),
   188     stack()->slot_addr(stack()->pc_slot_offset()));
   190   // Set up the Java frame anchor
   191   stack()->CreateSetLastJavaFrame();
   193   // Lock if necessary
   194   if (is_synchronized())
   195     Unimplemented();
   197   // Change the thread state to _thread_in_native
   198   CreateSetThreadState(_thread_in_native);
   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());
   216   // Start the transition back to _thread_in_Java
   217   CreateSetThreadState(_thread_in_native_trans);
   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   }
   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");
   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");
   240   builder()->CreateCondBr(
   241     builder()->CreateICmpNE(
   242       global_state,
   243       LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)),
   244     do_safepoint, check_thread);
   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");
   253   builder()->CreateCondBr(
   254     builder()->CreateICmpNE(
   255       thread_state,
   256       LLVMValue::jint_constant(0)),
   257     do_safepoint, safepointed);
   259   builder()->SetInsertPoint(do_safepoint);
   260   builder()->CreateCall(
   261     builder()->check_special_condition_for_native_trans(), thread);
   262   builder()->CreateBr(safepointed);
   264   // Finally we can change the thread state to _thread_in_Java
   265   builder()->SetInsertPoint(safepointed);
   266   CreateSetThreadState(_thread_in_Java);
   268   // Clear the frame anchor
   269   stack()->CreateResetLastJavaFrame();
   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");
   277   builder()->CreateCondBr(
   278     builder()->CreateICmpEQ(
   279       CreateLoadPendingException(),
   280       LLVMValue::null()),
   281     no_exception, exception);
   283   builder()->SetInsertPoint(exception);
   284   CreateResetHandleBlock();
   285   stack()->CreatePopFrame(0);
   286   builder()->CreateRet(LLVMValue::jint_constant(0));
   288   builder()->SetInsertPoint(no_exception);
   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");
   297     builder()->CreateCondBr(
   298       builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)),
   299       not_null, merge);
   301     builder()->SetInsertPoint(not_null);
   302     Value *unboxed_result = builder()->CreateLoad(result);
   303     builder()->CreateBr(merge);
   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   }
   312   // Reset handle block
   313   CreateResetHandleBlock();
   315   // Unlock if necessary.
   316   if (is_synchronized())
   317     Unimplemented();
   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;
   330     case T_CHAR:
   331       needs_cast = true;
   332       break;
   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     }
   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 }

mercurial