blob: 15e367f59bc273d89e84abb765e781a0361a82a1 [file] [log] [blame]
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_SHARK_SHARKSTACK_HPP
#define SHARE_VM_SHARK_SHARKSTACK_HPP
#include "shark/llvmHeaders.hpp"
#include "shark/sharkInvariants.hpp"
#include "shark/sharkType.hpp"
class SharkFunction;
class SharkNativeWrapper;
class SharkStackWithNormalFrame;
class SharkStackWithNativeFrame;
class SharkStack : public SharkCompileInvariants {
public:
static SharkStack* CreateBuildAndPushFrame(
SharkFunction* function, llvm::Value* method);
static SharkStack* CreateBuildAndPushFrame(
SharkNativeWrapper* wrapper, llvm::Value* method);
protected:
SharkStack(const SharkCompileInvariants* parent)
: SharkCompileInvariants(parent) {}
protected:
void initialize(llvm::Value* method);
protected:
void CreateStackOverflowCheck(llvm::Value* sp);
// Properties of the method being compiled
protected:
virtual int arg_size() const = 0;
virtual int max_locals() const = 0;
virtual int max_stack() const = 0;
virtual int max_monitors() const = 0;
// BasicBlock creation
protected:
virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0;
// Interpreter entry point for bailouts
protected:
virtual address interpreter_entry_point() const = 0;
// Interface with the Zero stack
private:
llvm::Value* zero_stack() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::zero_stack_offset(),
SharkType::zeroStack_type(),
"zero_stack");
}
llvm::Value* stack_base() const {
return builder()->CreateValueOfStructEntry(
zero_stack(),
ZeroStack::base_offset(),
SharkType::intptr_type(),
"stack_base");
}
llvm::Value* stack_pointer_addr() const {
return builder()->CreateAddressOfStructEntry(
zero_stack(),
ZeroStack::sp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"stack_pointer_addr");
}
llvm::Value* frame_pointer_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::top_zero_frame_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"frame_pointer_addr");
}
public:
llvm::LoadInst* CreateLoadStackPointer(const char *name = "") {
return builder()->CreateLoad(stack_pointer_addr(), name);
}
llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) {
return builder()->CreateStore(value, stack_pointer_addr());
}
llvm::LoadInst* CreateLoadFramePointer(const char *name = "") {
return builder()->CreateLoad(frame_pointer_addr(), name);
}
llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) {
return builder()->CreateStore(value, frame_pointer_addr());
}
llvm::Value* CreatePopFrame(int result_slots);
// Interface with the frame anchor
private:
llvm::Value* last_Java_sp_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::last_Java_sp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"last_Java_sp_addr");
}
llvm::Value* last_Java_fp_addr() const {
return builder()->CreateAddressOfStructEntry(
thread(),
JavaThread::last_Java_fp_offset(),
llvm::PointerType::getUnqual(SharkType::intptr_type()),
"last_Java_fp_addr");
}
public:
void CreateSetLastJavaFrame() {
// Note that whenever _last_Java_sp != NULL other anchor fields
// must be valid. The profiler apparently depends on this.
NOT_PRODUCT(CreateAssertLastJavaSPIsNull());
builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr());
// XXX There's last_Java_pc as well, but I don't think anything uses it
// Also XXX: should we fence here? Zero doesn't...
builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr());
// Also also XXX: we could probably cache the sp (and the fp we know??)
}
void CreateResetLastJavaFrame() {
builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr());
}
private:
void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN;
// Our method's frame
private:
llvm::Value* _frame;
int _extended_frame_size;
int _stack_slots_offset;
public:
int extended_frame_size() const {
return _extended_frame_size;
}
int oopmap_frame_size() const {
return extended_frame_size() - arg_size();
}
// Offsets of things in the frame
private:
int _monitors_slots_offset;
int _oop_tmp_slot_offset;
int _method_slot_offset;
int _pc_slot_offset;
int _locals_slots_offset;
public:
int stack_slots_offset() const {
return _stack_slots_offset;
}
int oop_tmp_slot_offset() const {
return _oop_tmp_slot_offset;
}
int method_slot_offset() const {
return _method_slot_offset;
}
int pc_slot_offset() const {
return _pc_slot_offset;
}
int locals_slots_offset() const {
return _locals_slots_offset;
}
int monitor_offset(int index) const {
assert(index >= 0 && index < max_monitors(), "invalid monitor index");
return _monitors_slots_offset +
(max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size();
}
int monitor_object_offset(int index) const {
return monitor_offset(index) +
(BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
}
int monitor_header_offset(int index) const {
return monitor_offset(index) +
((BasicObjectLock::lock_offset_in_bytes() +
BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord);
}
// Addresses of things in the frame
public:
llvm::Value* slot_addr(int offset,
llvm::Type* type = NULL,
const char* name = "") const;
llvm::Value* monitor_addr(int index) const {
return slot_addr(
monitor_offset(index),
SharkType::monitor_type(),
"monitor");
}
llvm::Value* monitor_object_addr(int index) const {
return slot_addr(
monitor_object_offset(index),
SharkType::oop_type(),
"object_addr");
}
llvm::Value* monitor_header_addr(int index) const {
return slot_addr(
monitor_header_offset(index),
SharkType::intptr_type(),
"displaced_header_addr");
}
// oopmap helpers
public:
static int oopmap_slot_munge(int offset) {
return offset << (LogBytesPerWord - LogBytesPerInt);
}
static VMReg slot2reg(int offset) {
return VMRegImpl::stack2reg(oopmap_slot_munge(offset));
}
};
class SharkStackWithNormalFrame : public SharkStack {
friend class SharkStack;
protected:
SharkStackWithNormalFrame(SharkFunction* function, llvm::Value* method);
private:
SharkFunction* _function;
private:
SharkFunction* function() const {
return _function;
}
// Properties of the method being compiled
private:
int arg_size() const;
int max_locals() const;
int max_stack() const;
int max_monitors() const;
// BasicBlock creation
private:
llvm::BasicBlock* CreateBlock(const char* name = "") const;
// Interpreter entry point for bailouts
private:
address interpreter_entry_point() const;
};
class SharkStackWithNativeFrame : public SharkStack {
friend class SharkStack;
protected:
SharkStackWithNativeFrame(SharkNativeWrapper* wrapper, llvm::Value* method);
private:
SharkNativeWrapper* _wrapper;
private:
SharkNativeWrapper* wrapper() const {
return _wrapper;
}
// Properties of the method being compiled
private:
int arg_size() const;
int max_locals() const;
int max_stack() const;
int max_monitors() const;
// BasicBlock creation
private:
llvm::BasicBlock* CreateBlock(const char* name = "") const;
// Interpreter entry point for bailouts
private:
address interpreter_entry_point() const;
};
#endif // SHARE_VM_SHARK_SHARKSTACK_HPP