430N/A/*
3261N/A * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
430N/A * Copyright 2008, 2009, 2010 Red Hat, Inc.
430N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
430N/A *
430N/A * This code is free software; you can redistribute it and/or modify it
430N/A * under the terms of the GNU General Public License version 2 only, as
430N/A * published by the Free Software Foundation.
430N/A *
430N/A * This code is distributed in the hope that it will be useful, but WITHOUT
430N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
430N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
430N/A * version 2 for more details (a copy is included in the LICENSE file that
430N/A * accompanied this code).
430N/A *
430N/A * You should have received a copy of the GNU General Public License version
430N/A * 2 along with this work; if not, write to the Free Software Foundation,
430N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2362N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
430N/A * questions.
430N/A *
430N/A */
430N/A
430N/A#ifndef SHARE_VM_SHARK_SHARKSTACK_HPP
430N/A#define SHARE_VM_SHARK_SHARKSTACK_HPP
430N/A
430N/A#include "shark/llvmHeaders.hpp"
430N/A#include "shark/sharkInvariants.hpp"
430N/A#include "shark/sharkType.hpp"
430N/A
430N/Aclass SharkFunction;
430N/Aclass SharkNativeWrapper;
430N/Aclass SharkStackWithNormalFrame;
430N/Aclass SharkStackWithNativeFrame;
430N/A
430N/Aclass SharkStack : public SharkCompileInvariants {
430N/A public:
430N/A static SharkStack* CreateBuildAndPushFrame(
430N/A SharkFunction* function, llvm::Value* method);
430N/A static SharkStack* CreateBuildAndPushFrame(
430N/A SharkNativeWrapper* wrapper, llvm::Value* method);
430N/A
430N/A protected:
430N/A SharkStack(const SharkCompileInvariants* parent)
430N/A : SharkCompileInvariants(parent) {}
430N/A
430N/A protected:
430N/A void initialize(llvm::Value* method);
430N/A
430N/A protected:
430N/A void CreateStackOverflowCheck(llvm::Value* sp);
430N/A
430N/A // Properties of the method being compiled
430N/A protected:
430N/A virtual int arg_size() const = 0;
430N/A virtual int max_locals() const = 0;
430N/A virtual int max_stack() const = 0;
430N/A virtual int max_monitors() const = 0;
430N/A
430N/A // BasicBlock creation
430N/A protected:
430N/A virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0;
430N/A
430N/A // Interpreter entry point for bailouts
430N/A protected:
430N/A virtual address interpreter_entry_point() const = 0;
430N/A
430N/A // Interface with the Zero stack
430N/A private:
430N/A llvm::Value* zero_stack() const {
430N/A return builder()->CreateAddressOfStructEntry(
430N/A thread(),
430N/A JavaThread::zero_stack_offset(),
430N/A SharkType::zeroStack_type(),
430N/A "zero_stack");
430N/A }
430N/A llvm::Value* stack_base() const {
430N/A return builder()->CreateValueOfStructEntry(
430N/A zero_stack(),
430N/A ZeroStack::base_offset(),
430N/A SharkType::intptr_type(),
430N/A "stack_base");
430N/A }
430N/A llvm::Value* stack_pointer_addr() const {
430N/A return builder()->CreateAddressOfStructEntry(
430N/A zero_stack(),
430N/A ZeroStack::sp_offset(),
430N/A llvm::PointerType::getUnqual(SharkType::intptr_type()),
430N/A "stack_pointer_addr");
430N/A }
430N/A llvm::Value* frame_pointer_addr() const {
430N/A return builder()->CreateAddressOfStructEntry(
430N/A thread(),
430N/A JavaThread::top_zero_frame_offset(),
430N/A llvm::PointerType::getUnqual(SharkType::intptr_type()),
430N/A "frame_pointer_addr");
430N/A }
430N/A
430N/A public:
430N/A llvm::LoadInst* CreateLoadStackPointer(const char *name = "") {
430N/A return builder()->CreateLoad(stack_pointer_addr(), name);
430N/A }
430N/A llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) {
430N/A return builder()->CreateStore(value, stack_pointer_addr());
430N/A }
430N/A llvm::LoadInst* CreateLoadFramePointer(const char *name = "") {
430N/A return builder()->CreateLoad(frame_pointer_addr(), name);
430N/A }
430N/A llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) {
430N/A return builder()->CreateStore(value, frame_pointer_addr());
430N/A }
430N/A llvm::Value* CreatePopFrame(int result_slots);
430N/A
430N/A // Interface with the frame anchor
430N/A private:
430N/A llvm::Value* last_Java_sp_addr() const {
430N/A return builder()->CreateAddressOfStructEntry(
430N/A thread(),
430N/A JavaThread::last_Java_sp_offset(),
430N/A llvm::PointerType::getUnqual(SharkType::intptr_type()),
3019N/A "last_Java_sp_addr");
3019N/A }
3019N/A llvm::Value* last_Java_fp_addr() const {
430N/A return builder()->CreateAddressOfStructEntry(
430N/A thread(),
430N/A JavaThread::last_Java_fp_offset(),
430N/A llvm::PointerType::getUnqual(SharkType::intptr_type()),
430N/A "last_Java_fp_addr");
430N/A }
430N/A
430N/A public:
430N/A void CreateSetLastJavaFrame() {
430N/A // Note that whenever _last_Java_sp != NULL other anchor fields
430N/A // must be valid. The profiler apparently depends on this.
430N/A NOT_PRODUCT(CreateAssertLastJavaSPIsNull());
430N/A builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr());
430N/A // XXX There's last_Java_pc as well, but I don't think anything uses it
430N/A // Also XXX: should we fence here? Zero doesn't...
430N/A builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr());
430N/A // Also also XXX: we could probably cache the sp (and the fp we know??)
430N/A }
430N/A void CreateResetLastJavaFrame() {
430N/A builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr());
430N/A }
430N/A
430N/A private:
430N/A void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN;
430N/A
430N/A // Our method's frame
430N/A private:
430N/A llvm::Value* _frame;
430N/A int _extended_frame_size;
430N/A int _stack_slots_offset;
430N/A
430N/A public:
430N/A int extended_frame_size() const {
430N/A 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,
const 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