src/hotspot/share/shark/sharkIntrinsics.cpp
changeset 47701 be620a591379
parent 47519 b1f360639517
parent 47700 c6d2381c6932
child 47702 cf8310446245
child 55762 e947a3a50a95
child 55767 8e22715afabc
child 55771 164d1a901f6e
equal deleted inserted replaced
47519:b1f360639517 47701:be620a591379
     1 /*
       
     2  * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * Copyright 2009 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 "precompiled.hpp"
       
    27 #include "ci/ciMethod.hpp"
       
    28 #include "shark/llvmHeaders.hpp"
       
    29 #include "shark/sharkIntrinsics.hpp"
       
    30 #include "shark/sharkState.hpp"
       
    31 #include "shark/sharkValue.hpp"
       
    32 #include "shark/shark_globals.hpp"
       
    33 
       
    34 using namespace llvm;
       
    35 
       
    36 bool SharkIntrinsics::is_intrinsic(ciMethod *target) {
       
    37   switch (target->intrinsic_id()) {
       
    38   case vmIntrinsics::_none:
       
    39     return false;
       
    40 
       
    41     // java.lang.Math
       
    42   case vmIntrinsics::_min:
       
    43   case vmIntrinsics::_max:
       
    44   case vmIntrinsics::_dabs:
       
    45   case vmIntrinsics::_dsin:
       
    46   case vmIntrinsics::_dcos:
       
    47   case vmIntrinsics::_dtan:
       
    48   case vmIntrinsics::_datan2:
       
    49   case vmIntrinsics::_dsqrt:
       
    50   case vmIntrinsics::_dlog:
       
    51   case vmIntrinsics::_dlog10:
       
    52   case vmIntrinsics::_dpow:
       
    53   case vmIntrinsics::_dexp:
       
    54     return true;
       
    55 
       
    56     // java.lang.Object
       
    57   case vmIntrinsics::_getClass:
       
    58     return true;
       
    59 
       
    60     // java.lang.System
       
    61   case vmIntrinsics::_currentTimeMillis:
       
    62     return true;
       
    63 
       
    64     // java.lang.Thread
       
    65   case vmIntrinsics::_currentThread:
       
    66     return true;
       
    67 
       
    68     // Unsafe
       
    69   case vmIntrinsics::_compareAndSetInt:
       
    70     return true;
       
    71 
       
    72   default:
       
    73     if (SharkPerformanceWarnings) {
       
    74       warning(
       
    75         "unhandled intrinsic vmIntrinsic::%s",
       
    76         vmIntrinsics::name_at(target->intrinsic_id()));
       
    77     }
       
    78   }
       
    79   return false;
       
    80 }
       
    81 
       
    82 void SharkIntrinsics::inline_intrinsic(ciMethod *target, SharkState *state) {
       
    83   SharkIntrinsics intrinsic(state, target);
       
    84   intrinsic.do_intrinsic();
       
    85 }
       
    86 
       
    87 void SharkIntrinsics::do_intrinsic() {
       
    88   switch (target()->intrinsic_id()) {
       
    89     // java.lang.Math
       
    90   case vmIntrinsics::_min:
       
    91     do_Math_minmax(llvm::ICmpInst::ICMP_SLE);
       
    92     break;
       
    93   case vmIntrinsics::_max:
       
    94     do_Math_minmax(llvm::ICmpInst::ICMP_SGE);
       
    95     break;
       
    96   case vmIntrinsics::_dabs:
       
    97     do_Math_1to1(builder()->fabs());
       
    98     break;
       
    99   case vmIntrinsics::_dsin:
       
   100     do_Math_1to1(builder()->sin());
       
   101     break;
       
   102   case vmIntrinsics::_dcos:
       
   103     do_Math_1to1(builder()->cos());
       
   104     break;
       
   105   case vmIntrinsics::_dtan:
       
   106     do_Math_1to1(builder()->tan());
       
   107     break;
       
   108   case vmIntrinsics::_datan2:
       
   109     do_Math_2to1(builder()->atan2());
       
   110     break;
       
   111   case vmIntrinsics::_dsqrt:
       
   112     do_Math_1to1(builder()->sqrt());
       
   113     break;
       
   114   case vmIntrinsics::_dlog:
       
   115     do_Math_1to1(builder()->log());
       
   116     break;
       
   117   case vmIntrinsics::_dlog10:
       
   118     do_Math_1to1(builder()->log10());
       
   119     break;
       
   120   case vmIntrinsics::_dpow:
       
   121     do_Math_2to1(builder()->pow());
       
   122     break;
       
   123   case vmIntrinsics::_dexp:
       
   124     do_Math_1to1(builder()->exp());
       
   125     break;
       
   126 
       
   127     // java.lang.Object
       
   128   case vmIntrinsics::_getClass:
       
   129     do_Object_getClass();
       
   130     break;
       
   131 
       
   132     // java.lang.System
       
   133   case vmIntrinsics::_currentTimeMillis:
       
   134     do_System_currentTimeMillis();
       
   135     break;
       
   136 
       
   137     // java.lang.Thread
       
   138   case vmIntrinsics::_currentThread:
       
   139     do_Thread_currentThread();
       
   140     break;
       
   141 
       
   142     // Unsafe
       
   143   case vmIntrinsics::_compareAndSetInt:
       
   144     do_Unsafe_compareAndSetInt();
       
   145     break;
       
   146 
       
   147   default:
       
   148     ShouldNotReachHere();
       
   149   }
       
   150 }
       
   151 
       
   152 void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) {
       
   153   // Pop the arguments
       
   154   SharkValue *sb = state()->pop();
       
   155   SharkValue *sa = state()->pop();
       
   156   Value *a = sa->jint_value();
       
   157   Value *b = sb->jint_value();
       
   158 
       
   159   // Perform the test
       
   160   BasicBlock *ip       = builder()->GetBlockInsertionPoint();
       
   161   BasicBlock *return_a = builder()->CreateBlock(ip, "return_a");
       
   162   BasicBlock *return_b = builder()->CreateBlock(ip, "return_b");
       
   163   BasicBlock *done     = builder()->CreateBlock(ip, "done");
       
   164 
       
   165   builder()->CreateCondBr(builder()->CreateICmp(p, a, b), return_a, return_b);
       
   166 
       
   167   builder()->SetInsertPoint(return_a);
       
   168   builder()->CreateBr(done);
       
   169 
       
   170   builder()->SetInsertPoint(return_b);
       
   171   builder()->CreateBr(done);
       
   172 
       
   173   builder()->SetInsertPoint(done);
       
   174   PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result");
       
   175   phi->addIncoming(a, return_a);
       
   176   phi->addIncoming(b, return_b);
       
   177 
       
   178   // Push the result
       
   179   state()->push(
       
   180     SharkValue::create_jint(
       
   181       phi,
       
   182       sa->zero_checked() && sb->zero_checked()));
       
   183 }
       
   184 
       
   185 void SharkIntrinsics::do_Math_1to1(Value *function) {
       
   186   SharkValue *empty = state()->pop();
       
   187   assert(empty == NULL, "should be");
       
   188   state()->push(
       
   189     SharkValue::create_jdouble(
       
   190       builder()->CreateCall(
       
   191         function, state()->pop()->jdouble_value())));
       
   192   state()->push(NULL);
       
   193 }
       
   194 
       
   195 void SharkIntrinsics::do_Math_2to1(Value *function) {
       
   196   SharkValue *empty = state()->pop();
       
   197   assert(empty == NULL, "should be");
       
   198   Value *y = state()->pop()->jdouble_value();
       
   199   empty = state()->pop();
       
   200   assert(empty == NULL, "should be");
       
   201   Value *x = state()->pop()->jdouble_value();
       
   202 
       
   203   state()->push(
       
   204     SharkValue::create_jdouble(
       
   205       builder()->CreateCall2(function, x, y)));
       
   206   state()->push(NULL);
       
   207 }
       
   208 
       
   209 void SharkIntrinsics::do_Object_getClass() {
       
   210   Value *klass = builder()->CreateValueOfStructEntry(
       
   211     state()->pop()->jobject_value(),
       
   212     in_ByteSize(oopDesc::klass_offset_in_bytes()),
       
   213     SharkType::klass_type(),
       
   214     "klass");
       
   215 
       
   216   state()->push(
       
   217     SharkValue::create_jobject(
       
   218       builder()->CreateValueOfStructEntry(
       
   219         klass,
       
   220         Klass::java_mirror_offset(),
       
   221         SharkType::oop_type(),
       
   222         "java_mirror"),
       
   223       true));
       
   224 }
       
   225 
       
   226 void SharkIntrinsics::do_System_currentTimeMillis() {
       
   227   state()->push(
       
   228     SharkValue::create_jlong(
       
   229       builder()->CreateCall(builder()->current_time_millis()),
       
   230       false));
       
   231   state()->push(NULL);
       
   232 }
       
   233 
       
   234 void SharkIntrinsics::do_Thread_currentThread() {
       
   235   state()->push(
       
   236     SharkValue::create_jobject(
       
   237       builder()->CreateValueOfStructEntry(
       
   238         thread(), JavaThread::threadObj_offset(),
       
   239         SharkType::oop_type(),
       
   240         "threadObj"),
       
   241       true));
       
   242 }
       
   243 
       
   244 void SharkIntrinsics::do_Unsafe_compareAndSetInt() {
       
   245   // Pop the arguments
       
   246   Value *x      = state()->pop()->jint_value();
       
   247   Value *e      = state()->pop()->jint_value();
       
   248   SharkValue *empty = state()->pop();
       
   249   assert(empty == NULL, "should be");
       
   250   Value *offset = state()->pop()->jlong_value();
       
   251   Value *object = state()->pop()->jobject_value();
       
   252   Value *unsafe = state()->pop()->jobject_value();
       
   253 
       
   254   // Convert the offset
       
   255   offset = builder()->CreateCall(
       
   256     builder()->unsafe_field_offset_to_byte_offset(),
       
   257     offset);
       
   258 
       
   259   // Locate the field
       
   260   Value *addr = builder()->CreateIntToPtr(
       
   261     builder()->CreateAdd(
       
   262       builder()->CreatePtrToInt(object, SharkType::intptr_type()),
       
   263       builder()->CreateIntCast(offset, SharkType::intptr_type(), true)),
       
   264     PointerType::getUnqual(SharkType::jint_type()),
       
   265     "addr");
       
   266 
       
   267   // Perform the operation
       
   268   Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent);
       
   269   // Push the result
       
   270   state()->push(
       
   271     SharkValue::create_jint(
       
   272       builder()->CreateIntCast(
       
   273         builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true),
       
   274       false));
       
   275 }