twisti@2047: /* stefank@2314: * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. twisti@2047: * Copyright 2009 Red Hat, Inc. twisti@2047: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. twisti@2047: * twisti@2047: * This code is free software; you can redistribute it and/or modify it twisti@2047: * under the terms of the GNU General Public License version 2 only, as twisti@2047: * published by the Free Software Foundation. twisti@2047: * twisti@2047: * This code is distributed in the hope that it will be useful, but WITHOUT twisti@2047: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or twisti@2047: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License twisti@2047: * version 2 for more details (a copy is included in the LICENSE file that twisti@2047: * accompanied this code). twisti@2047: * twisti@2047: * You should have received a copy of the GNU General Public License version twisti@2047: * 2 along with this work; if not, write to the Free Software Foundation, twisti@2047: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. twisti@2047: * twisti@2047: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA twisti@2047: * or visit www.oracle.com if you need additional information or have any twisti@2047: * questions. twisti@2047: * twisti@2047: */ twisti@2047: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "ci/ciMethod.hpp" stefank@2314: #include "shark/llvmHeaders.hpp" stefank@2314: #include "shark/sharkIntrinsics.hpp" stefank@2314: #include "shark/sharkState.hpp" stefank@2314: #include "shark/sharkValue.hpp" stefank@2314: #include "shark/shark_globals.hpp" twisti@2047: twisti@2047: using namespace llvm; twisti@2047: twisti@2047: bool SharkIntrinsics::is_intrinsic(ciMethod *target) { twisti@2047: switch (target->intrinsic_id()) { twisti@2047: case vmIntrinsics::_none: twisti@2047: return false; twisti@2047: twisti@2047: // java.lang.Math twisti@2047: case vmIntrinsics::_min: twisti@2047: case vmIntrinsics::_max: twisti@2047: case vmIntrinsics::_dabs: twisti@2047: case vmIntrinsics::_dsin: twisti@2047: case vmIntrinsics::_dcos: twisti@2047: case vmIntrinsics::_dtan: twisti@2047: case vmIntrinsics::_datan2: twisti@2047: case vmIntrinsics::_dsqrt: twisti@2047: case vmIntrinsics::_dlog: twisti@2047: case vmIntrinsics::_dlog10: twisti@2047: case vmIntrinsics::_dpow: twisti@2047: case vmIntrinsics::_dexp: twisti@2047: return true; twisti@2047: twisti@2047: // java.lang.Object twisti@2047: case vmIntrinsics::_getClass: twisti@2047: return true; twisti@2047: twisti@2047: // java.lang.System twisti@2047: case vmIntrinsics::_currentTimeMillis: twisti@2047: return true; twisti@2047: twisti@2047: // java.lang.Thread twisti@2047: case vmIntrinsics::_currentThread: twisti@2047: return true; twisti@2047: twisti@2047: // sun.misc.Unsafe twisti@2047: case vmIntrinsics::_compareAndSwapInt: twisti@2047: return true; twisti@2047: twisti@2047: default: twisti@2047: if (SharkPerformanceWarnings) { twisti@2047: warning( twisti@2047: "unhandled intrinsic vmIntrinsic::%s", twisti@2047: vmIntrinsics::name_at(target->intrinsic_id())); twisti@2047: } twisti@2047: } twisti@2047: return false; twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::inline_intrinsic(ciMethod *target, SharkState *state) { twisti@2047: SharkIntrinsics intrinsic(state, target); twisti@2047: intrinsic.do_intrinsic(); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_intrinsic() { twisti@2047: switch (target()->intrinsic_id()) { twisti@2047: // java.lang.Math twisti@2047: case vmIntrinsics::_min: twisti@2047: do_Math_minmax(llvm::ICmpInst::ICMP_SLE); twisti@2047: break; twisti@2047: case vmIntrinsics::_max: twisti@2047: do_Math_minmax(llvm::ICmpInst::ICMP_SGE); twisti@2047: break; twisti@2047: case vmIntrinsics::_dabs: twisti@2047: do_Math_1to1(builder()->fabs()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dsin: twisti@2047: do_Math_1to1(builder()->sin()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dcos: twisti@2047: do_Math_1to1(builder()->cos()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dtan: twisti@2047: do_Math_1to1(builder()->tan()); twisti@2047: break; twisti@2047: case vmIntrinsics::_datan2: twisti@2047: do_Math_2to1(builder()->atan2()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dsqrt: twisti@2047: do_Math_1to1(builder()->sqrt()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dlog: twisti@2047: do_Math_1to1(builder()->log()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dlog10: twisti@2047: do_Math_1to1(builder()->log10()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dpow: twisti@2047: do_Math_2to1(builder()->pow()); twisti@2047: break; twisti@2047: case vmIntrinsics::_dexp: twisti@2047: do_Math_1to1(builder()->exp()); twisti@2047: break; twisti@2047: twisti@2047: // java.lang.Object twisti@2047: case vmIntrinsics::_getClass: twisti@2047: do_Object_getClass(); twisti@2047: break; twisti@2047: twisti@2047: // java.lang.System twisti@2047: case vmIntrinsics::_currentTimeMillis: twisti@2047: do_System_currentTimeMillis(); twisti@2047: break; twisti@2047: twisti@2047: // java.lang.Thread twisti@2047: case vmIntrinsics::_currentThread: twisti@2047: do_Thread_currentThread(); twisti@2047: break; twisti@2047: twisti@2047: // sun.misc.Unsafe twisti@2047: case vmIntrinsics::_compareAndSwapInt: twisti@2047: do_Unsafe_compareAndSwapInt(); twisti@2047: break; twisti@2047: twisti@2047: default: twisti@2047: ShouldNotReachHere(); twisti@2047: } twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) { twisti@2047: // Pop the arguments twisti@2047: SharkValue *sb = state()->pop(); twisti@2047: SharkValue *sa = state()->pop(); twisti@2047: Value *a = sa->jint_value(); twisti@2047: Value *b = sb->jint_value(); twisti@2047: twisti@2047: // Perform the test twisti@2047: BasicBlock *ip = builder()->GetBlockInsertionPoint(); twisti@2047: BasicBlock *return_a = builder()->CreateBlock(ip, "return_a"); twisti@2047: BasicBlock *return_b = builder()->CreateBlock(ip, "return_b"); twisti@2047: BasicBlock *done = builder()->CreateBlock(ip, "done"); twisti@2047: twisti@2047: builder()->CreateCondBr(builder()->CreateICmp(p, a, b), return_a, return_b); twisti@2047: twisti@2047: builder()->SetInsertPoint(return_a); twisti@2047: builder()->CreateBr(done); twisti@2047: twisti@2047: builder()->SetInsertPoint(return_b); twisti@2047: builder()->CreateBr(done); twisti@2047: twisti@2047: builder()->SetInsertPoint(done); twisti@4314: PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result"); twisti@2047: phi->addIncoming(a, return_a); twisti@2047: phi->addIncoming(b, return_b); twisti@2047: twisti@2047: // Push the result twisti@2047: state()->push( twisti@2047: SharkValue::create_jint( twisti@2047: phi, twisti@2047: sa->zero_checked() && sb->zero_checked())); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Math_1to1(Value *function) { twisti@2047: SharkValue *empty = state()->pop(); twisti@2047: assert(empty == NULL, "should be"); twisti@2047: state()->push( twisti@2047: SharkValue::create_jdouble( twisti@2047: builder()->CreateCall( twisti@2047: function, state()->pop()->jdouble_value()))); twisti@2047: state()->push(NULL); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Math_2to1(Value *function) { twisti@2047: SharkValue *empty = state()->pop(); twisti@2047: assert(empty == NULL, "should be"); twisti@2047: Value *y = state()->pop()->jdouble_value(); twisti@2047: empty = state()->pop(); twisti@2047: assert(empty == NULL, "should be"); twisti@2047: Value *x = state()->pop()->jdouble_value(); twisti@2047: twisti@2047: state()->push( twisti@2047: SharkValue::create_jdouble( twisti@2047: builder()->CreateCall2(function, x, y))); twisti@2047: state()->push(NULL); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Object_getClass() { twisti@2047: Value *klass = builder()->CreateValueOfStructEntry( twisti@2047: state()->pop()->jobject_value(), twisti@2047: in_ByteSize(oopDesc::klass_offset_in_bytes()), twisti@4314: SharkType::klass_type(), twisti@2047: "klass"); twisti@2047: twisti@2047: state()->push( twisti@2047: SharkValue::create_jobject( twisti@2047: builder()->CreateValueOfStructEntry( stefank@3391: klass, stefank@3391: Klass::java_mirror_offset(), twisti@2047: SharkType::oop_type(), twisti@2047: "java_mirror"), twisti@2047: true)); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_System_currentTimeMillis() { twisti@2047: state()->push( twisti@2047: SharkValue::create_jlong( twisti@2047: builder()->CreateCall(builder()->current_time_millis()), twisti@2047: false)); twisti@2047: state()->push(NULL); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Thread_currentThread() { twisti@2047: state()->push( twisti@2047: SharkValue::create_jobject( twisti@2047: builder()->CreateValueOfStructEntry( twisti@2047: thread(), JavaThread::threadObj_offset(), twisti@2047: SharkType::oop_type(), twisti@2047: "threadObj"), twisti@2047: true)); twisti@2047: } twisti@2047: twisti@2047: void SharkIntrinsics::do_Unsafe_compareAndSwapInt() { twisti@2047: // Pop the arguments twisti@2047: Value *x = state()->pop()->jint_value(); twisti@2047: Value *e = state()->pop()->jint_value(); twisti@2047: SharkValue *empty = state()->pop(); twisti@2047: assert(empty == NULL, "should be"); twisti@2047: Value *offset = state()->pop()->jlong_value(); twisti@2047: Value *object = state()->pop()->jobject_value(); twisti@2047: Value *unsafe = state()->pop()->jobject_value(); twisti@2047: twisti@2047: // Convert the offset twisti@2047: offset = builder()->CreateCall( twisti@2047: builder()->unsafe_field_offset_to_byte_offset(), twisti@2047: offset); twisti@2047: twisti@2047: // Locate the field twisti@2047: Value *addr = builder()->CreateIntToPtr( twisti@2047: builder()->CreateAdd( twisti@2047: builder()->CreatePtrToInt(object, SharkType::intptr_type()), twisti@2047: builder()->CreateIntCast(offset, SharkType::intptr_type(), true)), twisti@2047: PointerType::getUnqual(SharkType::jint_type()), twisti@2047: "addr"); twisti@2047: twisti@2047: // Perform the operation twisti@4314: Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent); twisti@2047: // Push the result twisti@2047: state()->push( twisti@2047: SharkValue::create_jint( twisti@2047: builder()->CreateIntCast( twisti@2047: builder()->CreateICmpEQ(result, e), SharkType::jint_type(), true), twisti@2047: false)); twisti@2047: }