sharkStack.hpp revision 1879:f95d63e2154a
1/*
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2008, 2009, 2010 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#ifndef SHARE_VM_SHARK_SHARKSTACK_HPP
27#define SHARE_VM_SHARK_SHARKSTACK_HPP
28
29#include "shark/llvmHeaders.hpp"
30#include "shark/sharkInvariants.hpp"
31#include "shark/sharkType.hpp"
32
33class SharkFunction;
34class SharkNativeWrapper;
35class SharkStackWithNormalFrame;
36class SharkStackWithNativeFrame;
37
38class SharkStack : public SharkCompileInvariants {
39 public:
40  static SharkStack* CreateBuildAndPushFrame(
41    SharkFunction* function, llvm::Value* method);
42  static SharkStack* CreateBuildAndPushFrame(
43    SharkNativeWrapper* wrapper, llvm::Value* method);
44
45 protected:
46  SharkStack(const SharkCompileInvariants* parent)
47    : SharkCompileInvariants(parent) {}
48
49 protected:
50  void initialize(llvm::Value* method);
51
52 protected:
53  void CreateStackOverflowCheck(llvm::Value* sp);
54
55  // Properties of the method being compiled
56 protected:
57  virtual int arg_size() const = 0;
58  virtual int max_locals() const = 0;
59  virtual int max_stack() const = 0;
60  virtual int max_monitors() const = 0;
61
62  // BasicBlock creation
63 protected:
64  virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0;
65
66  // Interpreter entry point for bailouts
67 protected:
68  virtual address interpreter_entry_point() const = 0;
69
70  // Interface with the Zero stack
71 private:
72  llvm::Value* zero_stack() const {
73    return builder()->CreateAddressOfStructEntry(
74      thread(),
75      JavaThread::zero_stack_offset(),
76      SharkType::zeroStack_type(),
77      "zero_stack");
78  }
79  llvm::Value* stack_base() const {
80    return builder()->CreateValueOfStructEntry(
81      zero_stack(),
82      ZeroStack::base_offset(),
83      SharkType::intptr_type(),
84      "stack_base");
85  }
86  llvm::Value* stack_pointer_addr() const {
87    return builder()->CreateAddressOfStructEntry(
88      zero_stack(),
89      ZeroStack::sp_offset(),
90      llvm::PointerType::getUnqual(SharkType::intptr_type()),
91      "stack_pointer_addr");
92  }
93  llvm::Value* frame_pointer_addr() const {
94    return builder()->CreateAddressOfStructEntry(
95      thread(),
96      JavaThread::top_zero_frame_offset(),
97      llvm::PointerType::getUnqual(SharkType::intptr_type()),
98      "frame_pointer_addr");
99  }
100
101 public:
102  llvm::LoadInst* CreateLoadStackPointer(const char *name = "") {
103    return builder()->CreateLoad(stack_pointer_addr(), name);
104  }
105  llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) {
106    return builder()->CreateStore(value, stack_pointer_addr());
107  }
108  llvm::LoadInst* CreateLoadFramePointer(const char *name = "") {
109    return builder()->CreateLoad(frame_pointer_addr(), name);
110  }
111  llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) {
112    return builder()->CreateStore(value, frame_pointer_addr());
113  }
114  llvm::Value* CreatePopFrame(int result_slots);
115
116  // Interface with the frame anchor
117 private:
118  llvm::Value* last_Java_sp_addr() const {
119    return builder()->CreateAddressOfStructEntry(
120      thread(),
121      JavaThread::last_Java_sp_offset(),
122      llvm::PointerType::getUnqual(SharkType::intptr_type()),
123      "last_Java_sp_addr");
124  }
125  llvm::Value* last_Java_fp_addr() const {
126    return builder()->CreateAddressOfStructEntry(
127      thread(),
128      JavaThread::last_Java_fp_offset(),
129      llvm::PointerType::getUnqual(SharkType::intptr_type()),
130      "last_Java_fp_addr");
131  }
132
133 public:
134  void CreateSetLastJavaFrame() {
135    // Note that whenever _last_Java_sp != NULL other anchor fields
136    // must be valid.  The profiler apparently depends on this.
137    NOT_PRODUCT(CreateAssertLastJavaSPIsNull());
138    builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr());
139    // XXX There's last_Java_pc as well, but I don't think anything uses it
140    // Also XXX: should we fence here?  Zero doesn't...
141    builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr());
142    // Also also XXX: we could probably cache the sp (and the fp we know??)
143  }
144  void CreateResetLastJavaFrame() {
145    builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr());
146  }
147
148 private:
149  void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN;
150
151  // Our method's frame
152 private:
153  llvm::Value* _frame;
154  int          _extended_frame_size;
155  int          _stack_slots_offset;
156
157 public:
158  int extended_frame_size() const {
159    return _extended_frame_size;
160  }
161  int oopmap_frame_size() const {
162    return extended_frame_size() - arg_size();
163  }
164
165  // Offsets of things in the frame
166 private:
167  int _monitors_slots_offset;
168  int _oop_tmp_slot_offset;
169  int _method_slot_offset;
170  int _pc_slot_offset;
171  int _locals_slots_offset;
172
173 public:
174  int stack_slots_offset() const {
175    return _stack_slots_offset;
176  }
177  int oop_tmp_slot_offset() const {
178    return _oop_tmp_slot_offset;
179  }
180  int method_slot_offset() const {
181    return _method_slot_offset;
182  }
183  int pc_slot_offset() const {
184    return _pc_slot_offset;
185  }
186  int locals_slots_offset() const {
187    return _locals_slots_offset;
188  }
189  int monitor_offset(int index) const {
190    assert(index >= 0 && index < max_monitors(), "invalid monitor index");
191    return _monitors_slots_offset +
192      (max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size();
193  }
194  int monitor_object_offset(int index) const {
195    return monitor_offset(index) +
196      (BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord);
197  }
198  int monitor_header_offset(int index) const {
199    return monitor_offset(index) +
200      ((BasicObjectLock::lock_offset_in_bytes() +
201        BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord);
202  }
203
204  // Addresses of things in the frame
205 public:
206  llvm::Value* slot_addr(int               offset,
207                         const llvm::Type* type = NULL,
208                         const char*       name = "") const;
209
210  llvm::Value* monitor_addr(int index) const {
211    return slot_addr(
212      monitor_offset(index),
213      SharkType::monitor_type(),
214      "monitor");
215  }
216  llvm::Value* monitor_object_addr(int index) const {
217    return slot_addr(
218      monitor_object_offset(index),
219      SharkType::oop_type(),
220      "object_addr");
221  }
222  llvm::Value* monitor_header_addr(int index) const {
223    return slot_addr(
224      monitor_header_offset(index),
225      SharkType::intptr_type(),
226      "displaced_header_addr");
227  }
228
229  // oopmap helpers
230 public:
231  static int oopmap_slot_munge(int offset) {
232    return offset << (LogBytesPerWord - LogBytesPerInt);
233  }
234  static VMReg slot2reg(int offset) {
235    return VMRegImpl::stack2reg(oopmap_slot_munge(offset));
236  }
237};
238
239class SharkStackWithNormalFrame : public SharkStack {
240  friend class SharkStack;
241
242 protected:
243  SharkStackWithNormalFrame(SharkFunction* function, llvm::Value* method);
244
245 private:
246  SharkFunction* _function;
247
248 private:
249  SharkFunction* function() const {
250    return _function;
251  }
252
253  // Properties of the method being compiled
254 private:
255  int arg_size() const;
256  int max_locals() const;
257  int max_stack() const;
258  int max_monitors() const;
259
260  // BasicBlock creation
261 private:
262  llvm::BasicBlock* CreateBlock(const char* name = "") const;
263
264  // Interpreter entry point for bailouts
265 private:
266  address interpreter_entry_point() const;
267};
268
269class SharkStackWithNativeFrame : public SharkStack {
270  friend class SharkStack;
271
272 protected:
273  SharkStackWithNativeFrame(SharkNativeWrapper* wrapper, llvm::Value* method);
274
275 private:
276  SharkNativeWrapper* _wrapper;
277
278 private:
279  SharkNativeWrapper* wrapper() const {
280    return _wrapper;
281  }
282
283  // Properties of the method being compiled
284 private:
285  int arg_size() const;
286  int max_locals() const;
287  int max_stack() const;
288  int max_monitors() const;
289
290  // BasicBlock creation
291 private:
292  llvm::BasicBlock* CreateBlock(const char* name = "") const;
293
294  // Interpreter entry point for bailouts
295 private:
296  address interpreter_entry_point() const;
297};
298
299#endif // SHARE_VM_SHARK_SHARKSTACK_HPP
300