sharkBuilder.cpp revision 5776:de6a9e811145
1251876Speter/*
2251876Speter * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3251876Speter * Copyright 2008, 2009, 2010 Red Hat, Inc.
4251876Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5251876Speter *
6251876Speter * This code is free software; you can redistribute it and/or modify it
7251876Speter * under the terms of the GNU General Public License version 2 only, as
8251876Speter * published by the Free Software Foundation.
9251876Speter *
10251876Speter * This code is distributed in the hope that it will be useful, but WITHOUT
11251876Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12251876Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13251876Speter * version 2 for more details (a copy is included in the LICENSE file that
14251876Speter * accompanied this code).
15251876Speter *
16251876Speter * You should have received a copy of the GNU General Public License version
17251876Speter * 2 along with this work; if not, write to the Free Software Foundation,
18251876Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19251876Speter *
20251876Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21251876Speter * or visit www.oracle.com if you need additional information or have any
22251876Speter * questions.
23251876Speter *
24251876Speter */
25251876Speter
26251876Speter#include "precompiled.hpp"
27251876Speter#include "ci/ciMethod.hpp"
28251876Speter#include "memory/resourceArea.hpp"
29251876Speter#include "oops/method.hpp"
30251876Speter#include "runtime/os.hpp"
31251876Speter#include "runtime/synchronizer.hpp"
32251876Speter#include "runtime/thread.hpp"
33251876Speter#include "shark/llvmHeaders.hpp"
34251876Speter#include "shark/llvmValue.hpp"
35251876Speter#include "shark/sharkBuilder.hpp"
36251876Speter#include "shark/sharkContext.hpp"
37251876Speter#include "shark/sharkRuntime.hpp"
38251876Speter#include "utilities/debug.hpp"
39251876Speter
40251876Speterusing namespace llvm;
41251876Speter
42251876SpeterSharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer)
43251876Speter  : IRBuilder<>(SharkContext::current()),
44251876Speter    _code_buffer(code_buffer) {
45251876Speter}
46251876Speter
47251876Speter// Helpers for accessing structures
48251876SpeterValue* SharkBuilder::CreateAddressOfStructEntry(Value*      base,
49251876Speter                                                ByteSize    offset,
50251876Speter                                                Type* type,
51251876Speter                                                const char* name) {
52251876Speter  return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name);
53251876Speter}
54251876Speter
55LoadInst* SharkBuilder::CreateValueOfStructEntry(Value*      base,
56                                                 ByteSize    offset,
57                                                 Type* type,
58                                                 const char* name) {
59  return CreateLoad(
60    CreateAddressOfStructEntry(
61      base, offset, PointerType::getUnqual(type)),
62    name);
63}
64
65// Helpers for accessing arrays
66
67LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) {
68  return CreateValueOfStructEntry(
69    arrayoop, in_ByteSize(arrayOopDesc::length_offset_in_bytes()),
70    SharkType::jint_type(), "length");
71}
72
73Value* SharkBuilder::CreateArrayAddress(Value*      arrayoop,
74                                        Type* element_type,
75                                        int         element_bytes,
76                                        ByteSize    base_offset,
77                                        Value*      index,
78                                        const char* name) {
79  Value* offset = CreateIntCast(index, SharkType::intptr_type(), false);
80  if (element_bytes != 1)
81    offset = CreateShl(
82      offset,
83      LLVMValue::intptr_constant(exact_log2(element_bytes)));
84  offset = CreateAdd(
85    LLVMValue::intptr_constant(in_bytes(base_offset)), offset);
86
87  return CreateIntToPtr(
88    CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset),
89    PointerType::getUnqual(element_type),
90    name);
91}
92
93Value* SharkBuilder::CreateArrayAddress(Value*      arrayoop,
94                                        BasicType   basic_type,
95                                        ByteSize    base_offset,
96                                        Value*      index,
97                                        const char* name) {
98  return CreateArrayAddress(
99    arrayoop,
100    SharkType::to_arrayType(basic_type),
101    type2aelembytes(basic_type),
102    base_offset, index, name);
103}
104
105Value* SharkBuilder::CreateArrayAddress(Value*      arrayoop,
106                                        BasicType   basic_type,
107                                        Value*      index,
108                                        const char* name) {
109  return CreateArrayAddress(
110    arrayoop, basic_type,
111    in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)),
112    index, name);
113}
114
115// Helpers for creating intrinsics and external functions.
116
117Type* SharkBuilder::make_type(char type, bool void_ok) {
118  switch (type) {
119    // Primitive types
120  case 'c':
121    return SharkType::jbyte_type();
122  case 'i':
123    return SharkType::jint_type();
124  case 'l':
125    return SharkType::jlong_type();
126  case 'x':
127    return SharkType::intptr_type();
128  case 'f':
129    return SharkType::jfloat_type();
130  case 'd':
131    return SharkType::jdouble_type();
132
133    // Pointers to primitive types
134  case 'C':
135  case 'I':
136  case 'L':
137  case 'X':
138  case 'F':
139  case 'D':
140    return PointerType::getUnqual(make_type(tolower(type), false));
141
142    // VM objects
143  case 'T':
144    return SharkType::thread_type();
145  case 'M':
146    return PointerType::getUnqual(SharkType::monitor_type());
147  case 'O':
148    return SharkType::oop_type();
149  case 'K':
150    return SharkType::klass_type();
151
152    // Miscellaneous
153  case 'v':
154    assert(void_ok, "should be");
155    return SharkType::void_type();
156  case '1':
157    return SharkType::bit_type();
158
159  default:
160    ShouldNotReachHere();
161  }
162}
163
164FunctionType* SharkBuilder::make_ftype(const char* params,
165                                             const char* ret) {
166  std::vector<Type*> param_types;
167  for (const char* c = params; *c; c++)
168    param_types.push_back(make_type(*c, false));
169
170  assert(strlen(ret) == 1, "should be");
171  Type *return_type = make_type(*ret, true);
172
173  return FunctionType::get(return_type, param_types, false);
174}
175
176// Create an object representing an intrinsic or external function by
177// referencing the symbol by name.  This is the LLVM-style approach,
178// but it cannot be used on functions within libjvm.so its symbols
179// are not exported.  Note that you cannot make this work simply by
180// exporting the symbols, as some symbols have the same names as
181// symbols in the standard libraries (eg, atan2, fabs) and would
182// obscure them were they visible.
183Value* SharkBuilder::make_function(const char* name,
184                                   const char* params,
185                                   const char* ret) {
186  return SharkContext::current().get_external(name, make_ftype(params, ret));
187}
188
189// Create an object representing an external function by inlining a
190// function pointer in the code.  This is not the LLVM way, but it's
191// the only way to access functions in libjvm.so and functions like
192// __kernel_dmb on ARM which is accessed via an absolute address.
193Value* SharkBuilder::make_function(address     func,
194                                   const char* params,
195                                   const char* ret) {
196  return CreateIntToPtr(
197    LLVMValue::intptr_constant((intptr_t) func),
198    PointerType::getUnqual(make_ftype(params, ret)));
199}
200
201// VM calls
202
203Value* SharkBuilder::find_exception_handler() {
204  return make_function(
205    (address) SharkRuntime::find_exception_handler, "TIi", "i");
206}
207
208Value* SharkBuilder::monitorenter() {
209  return make_function((address) SharkRuntime::monitorenter, "TM", "v");
210}
211
212Value* SharkBuilder::monitorexit() {
213  return make_function((address) SharkRuntime::monitorexit, "TM", "v");
214}
215
216Value* SharkBuilder::new_instance() {
217  return make_function((address) SharkRuntime::new_instance, "Ti", "v");
218}
219
220Value* SharkBuilder::newarray() {
221  return make_function((address) SharkRuntime::newarray, "Tii", "v");
222}
223
224Value* SharkBuilder::anewarray() {
225  return make_function((address) SharkRuntime::anewarray, "Tii", "v");
226}
227
228Value* SharkBuilder::multianewarray() {
229  return make_function((address) SharkRuntime::multianewarray, "TiiI", "v");
230}
231
232Value* SharkBuilder::register_finalizer() {
233  return make_function((address) SharkRuntime::register_finalizer, "TO", "v");
234}
235
236Value* SharkBuilder::safepoint() {
237  return make_function((address) SafepointSynchronize::block, "T", "v");
238}
239
240Value* SharkBuilder::throw_ArithmeticException() {
241  return make_function(
242    (address) SharkRuntime::throw_ArithmeticException, "TCi", "v");
243}
244
245Value* SharkBuilder::throw_ArrayIndexOutOfBoundsException() {
246  return make_function(
247    (address) SharkRuntime::throw_ArrayIndexOutOfBoundsException, "TCii", "v");
248}
249
250Value* SharkBuilder::throw_ClassCastException() {
251  return make_function(
252    (address) SharkRuntime::throw_ClassCastException, "TCi", "v");
253}
254
255Value* SharkBuilder::throw_NullPointerException() {
256  return make_function(
257    (address) SharkRuntime::throw_NullPointerException, "TCi", "v");
258}
259
260// High-level non-VM calls
261
262Value* SharkBuilder::f2i() {
263  return make_function((address) SharedRuntime::f2i, "f", "i");
264}
265
266Value* SharkBuilder::f2l() {
267  return make_function((address) SharedRuntime::f2l, "f", "l");
268}
269
270Value* SharkBuilder::d2i() {
271  return make_function((address) SharedRuntime::d2i, "d", "i");
272}
273
274Value* SharkBuilder::d2l() {
275  return make_function((address) SharedRuntime::d2l, "d", "l");
276}
277
278Value* SharkBuilder::is_subtype_of() {
279  return make_function((address) SharkRuntime::is_subtype_of, "KK", "c");
280}
281
282Value* SharkBuilder::current_time_millis() {
283  return make_function((address) os::javaTimeMillis, "", "l");
284}
285
286Value* SharkBuilder::sin() {
287  return make_function("llvm.sin.f64", "d", "d");
288}
289
290Value* SharkBuilder::cos() {
291  return make_function("llvm.cos.f64", "d", "d");
292}
293
294Value* SharkBuilder::tan() {
295  return make_function((address) ::tan, "d", "d");
296}
297
298Value* SharkBuilder::atan2() {
299  return make_function((address) ::atan2, "dd", "d");
300}
301
302Value* SharkBuilder::sqrt() {
303  return make_function("llvm.sqrt.f64", "d", "d");
304}
305
306Value* SharkBuilder::log() {
307  return make_function("llvm.log.f64", "d", "d");
308}
309
310Value* SharkBuilder::log10() {
311  return make_function("llvm.log10.f64", "d", "d");
312}
313
314Value* SharkBuilder::pow() {
315  return make_function("llvm.pow.f64", "dd", "d");
316}
317
318Value* SharkBuilder::exp() {
319  return make_function("llvm.exp.f64", "d", "d");
320}
321
322Value* SharkBuilder::fabs() {
323  return make_function((address) ::fabs, "d", "d");
324}
325
326Value* SharkBuilder::unsafe_field_offset_to_byte_offset() {
327  extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset);
328  return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l");
329}
330
331Value* SharkBuilder::osr_migration_end() {
332  return make_function((address) SharedRuntime::OSR_migration_end, "C", "v");
333}
334
335// Semi-VM calls
336
337Value* SharkBuilder::throw_StackOverflowError() {
338  return make_function((address) ZeroStack::handle_overflow, "T", "v");
339}
340
341Value* SharkBuilder::uncommon_trap() {
342  return make_function((address) SharkRuntime::uncommon_trap, "Ti", "i");
343}
344
345Value* SharkBuilder::deoptimized_entry_point() {
346  return make_function((address) CppInterpreter::main_loop, "iT", "v");
347}
348
349// Native-Java transition
350
351Value* SharkBuilder::check_special_condition_for_native_trans() {
352  return make_function(
353    (address) JavaThread::check_special_condition_for_native_trans,
354    "T", "v");
355}
356
357Value* SharkBuilder::frame_address() {
358  return make_function("llvm.frameaddress", "i", "C");
359}
360
361Value* SharkBuilder::memset() {
362  // LLVM 2.8 added a fifth isVolatile field for memset
363  // introduced with LLVM r100304
364  return make_function("llvm.memset.p0i8.i32", "Cciii", "v");
365}
366
367Value* SharkBuilder::unimplemented() {
368  return make_function((address) report_unimplemented, "Ci", "v");
369}
370
371Value* SharkBuilder::should_not_reach_here() {
372  return make_function((address) report_should_not_reach_here, "Ci", "v");
373}
374
375Value* SharkBuilder::dump() {
376  return make_function((address) SharkRuntime::dump, "Cx", "v");
377}
378
379// Public interface to low-level non-VM calls
380
381CallInst* SharkBuilder::CreateGetFrameAddress() {
382  return CreateCall(frame_address(), LLVMValue::jint_constant(0));
383}
384
385CallInst* SharkBuilder::CreateMemset(Value* dst,
386                                     Value* value,
387                                     Value* len,
388                                     Value* align) {
389  return CreateCall5(memset(), dst, value, len, align,
390                     LLVMValue::jint_constant(0));
391}
392
393CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) {
394  return CreateCall2(
395    unimplemented(),
396    CreateIntToPtr(
397      LLVMValue::intptr_constant((intptr_t) file),
398      PointerType::getUnqual(SharkType::jbyte_type())),
399    LLVMValue::jint_constant(line));
400}
401
402CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) {
403  return CreateCall2(
404    should_not_reach_here(),
405    CreateIntToPtr(
406      LLVMValue::intptr_constant((intptr_t) file),
407      PointerType::getUnqual(SharkType::jbyte_type())),
408    LLVMValue::jint_constant(line));
409}
410
411#ifndef PRODUCT
412CallInst* SharkBuilder::CreateDump(Value* value) {
413  const char *name;
414  if (value->hasName())
415    // XXX this leaks, but it's only debug code
416    name = strdup(value->getName().str().c_str());
417  else
418    name = "unnamed_value";
419
420  if (isa<PointerType>(value->getType()))
421    value = CreatePtrToInt(value, SharkType::intptr_type());
422  else if (value->getType()->
423           isIntegerTy()
424           )
425    value = CreateIntCast(value, SharkType::intptr_type(), false);
426  else
427    Unimplemented();
428
429  return CreateCall2(
430    dump(),
431    CreateIntToPtr(
432      LLVMValue::intptr_constant((intptr_t) name),
433      PointerType::getUnqual(SharkType::jbyte_type())),
434    value);
435}
436#endif // PRODUCT
437
438// HotSpot memory barriers
439
440void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) {
441  if (bs->kind() != BarrierSet::CardTableModRef)
442    Unimplemented();
443
444  CreateStore(
445    LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
446    CreateIntToPtr(
447      CreateAdd(
448        LLVMValue::intptr_constant(
449          (intptr_t) ((CardTableModRefBS *) bs)->byte_map_base),
450        CreateLShr(
451          CreatePtrToInt(field, SharkType::intptr_type()),
452          LLVMValue::intptr_constant(CardTableModRefBS::card_shift))),
453      PointerType::getUnqual(SharkType::jbyte_type())));
454}
455
456// Helpers for accessing the code buffer
457
458Value* SharkBuilder::code_buffer_address(int offset) {
459  return CreateAdd(
460    code_buffer()->base_pc(),
461    LLVMValue::intptr_constant(offset));
462}
463
464Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) {
465  return CreateLoad(
466    CreateIntToPtr(
467      code_buffer_address(code_buffer()->inline_oop(object)),
468      PointerType::getUnqual(SharkType::oop_type())),
469    name);
470}
471
472Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) {
473  assert(metadata != NULL, "inlined metadata must not be NULL");
474  assert(metadata->is_metaspace_object(), "sanity check");
475  return CreateLoad(
476    CreateIntToPtr(
477      code_buffer_address(code_buffer()->inline_Metadata(metadata)),
478      PointerType::getUnqual(type)),
479    name);
480}
481
482Value* SharkBuilder::CreateInlineData(void*       data,
483                                      size_t      size,
484                                      Type* type,
485                                      const char* name) {
486  return CreateIntToPtr(
487    code_buffer_address(code_buffer()->inline_data(data, size)),
488    type,
489    name);
490}
491
492// Helpers for creating basic blocks.
493
494BasicBlock* SharkBuilder::GetBlockInsertionPoint() const {
495  BasicBlock *cur = GetInsertBlock();
496
497  // BasicBlock::Create takes an insertBefore argument, so
498  // we need to find the block _after_ the current block
499  Function::iterator iter = cur->getParent()->begin();
500  Function::iterator end  = cur->getParent()->end();
501  while (iter != end) {
502    iter++;
503    if (&*iter == cur) {
504      iter++;
505      break;
506    }
507  }
508
509  if (iter == end)
510    return NULL;
511  else
512    return iter;
513}
514
515BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const {
516  return BasicBlock::Create(
517    SharkContext::current(), name, GetInsertBlock()->getParent(), ip);
518}
519
520LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
521  return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name);
522}
523
524StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) {
525  return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name);
526}
527