--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/shark/sharkCacheDecache.hpp Wed Aug 11 05:51:21 2010 -0700
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2008, 2009 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.
+ *
+ */
+
+// Class hierarchy:
+// - SharkStateScanner
+// - SharkCacherDecacher
+// - SharkDecacher
+// - SharkJavaCallDecacher
+// - SharkVMCallDecacher
+// - SharkTrapDecacher
+// - SharkCacher
+// - SharkJavaCallCacher
+// - SharkVMCallCacher
+// - SharkFunctionEntryCacher
+// - SharkNormalEntryCacher
+// - SharkOSREntryCacher
+
+class SharkCacherDecacher : public SharkStateScanner {
+ protected:
+ SharkCacherDecacher(SharkFunction* function)
+ : SharkStateScanner(function) {}
+
+ // Helper
+ protected:
+ static int adjusted_offset(SharkValue* value, int offset) {
+ if (value->is_two_word())
+ offset--;
+ return offset;
+ }
+};
+
+class SharkDecacher : public SharkCacherDecacher {
+ protected:
+ SharkDecacher(SharkFunction* function, int bci)
+ : SharkCacherDecacher(function), _bci(bci) {}
+
+ private:
+ int _bci;
+
+ protected:
+ int bci() const {
+ return _bci;
+ }
+
+ private:
+ int _pc_offset;
+ OopMap* _oopmap;
+ GrowableArray<ScopeValue*>* _exparray;
+ GrowableArray<MonitorValue*>* _monarray;
+ GrowableArray<ScopeValue*>* _locarray;
+
+ private:
+ int pc_offset() const {
+ return _pc_offset;
+ }
+ OopMap* oopmap() const {
+ return _oopmap;
+ }
+ GrowableArray<ScopeValue*>* exparray() const {
+ return _exparray;
+ }
+ GrowableArray<MonitorValue*>* monarray() const {
+ return _monarray;
+ }
+ GrowableArray<ScopeValue*>* locarray() const {
+ return _locarray;
+ }
+
+ // Callbacks
+ protected:
+ void start_frame();
+
+ void start_stack(int stack_depth);
+ void process_stack_slot(int index, SharkValue** value, int offset);
+
+ void start_monitors(int num_monitors);
+ void process_monitor(int index, int box_offset, int obj_offset);
+
+ void process_oop_tmp_slot(llvm::Value** value, int offset);
+ void process_method_slot(llvm::Value** value, int offset);
+ void process_pc_slot(int offset);
+
+ void start_locals();
+ void process_local_slot(int index, SharkValue** value, int offset);
+
+ void end_frame();
+
+ // oopmap and debuginfo helpers
+ private:
+ static int oopmap_slot_munge(int offset) {
+ return SharkStack::oopmap_slot_munge(offset);
+ }
+ static VMReg slot2reg(int offset) {
+ return SharkStack::slot2reg(offset);
+ }
+ static Location slot2loc(int offset, Location::Type type) {
+ return Location::new_stk_loc(type, offset * wordSize);
+ }
+ static LocationValue* slot2lv(int offset, Location::Type type) {
+ return new LocationValue(slot2loc(offset, type));
+ }
+ static Location::Type location_type(SharkValue** addr, bool maybe_two_word) {
+ // low addresses this end
+ // Type 32-bit 64-bit
+ // ----------------------------------------------------
+ // stack[0] local[3] jobject oop oop
+ // stack[1] local[2] NULL normal lng
+ // stack[2] local[1] jlong normal invalid
+ // stack[3] local[0] jint normal normal
+ //
+ // high addresses this end
+
+ SharkValue *value = *addr;
+ if (value) {
+ if (value->is_jobject())
+ return Location::oop;
+#ifdef _LP64
+ if (value->is_two_word())
+ return Location::invalid;
+#endif // _LP64
+ return Location::normal;
+ }
+ else {
+ if (maybe_two_word) {
+ value = *(addr - 1);
+ if (value && value->is_two_word()) {
+#ifdef _LP64
+ if (value->is_jlong())
+ return Location::lng;
+ if (value->is_jdouble())
+ return Location::dbl;
+ ShouldNotReachHere();
+#else
+ return Location::normal;
+#endif // _LP64
+ }
+ }
+ return Location::invalid;
+ }
+ }
+
+ // Stack slot helpers
+ protected:
+ virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0;
+ virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0;
+ virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0;
+
+ static Location::Type stack_location_type(int index, SharkValue** addr) {
+ return location_type(addr, *addr == NULL);
+ }
+
+ // Local slot helpers
+ protected:
+ virtual bool local_slot_needs_write(int index, SharkValue* value) = 0;
+ virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0;
+ virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0;
+
+ static Location::Type local_location_type(int index, SharkValue** addr) {
+ return location_type(addr, index > 0);
+ }
+
+ // Writer helper
+ protected:
+ void write_value_to_frame(const llvm::Type* type,
+ llvm::Value* value,
+ int offset);
+};
+
+class SharkJavaCallDecacher : public SharkDecacher {
+ public:
+ SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee)
+ : SharkDecacher(function, bci), _callee(callee) {}
+
+ private:
+ ciMethod* _callee;
+
+ protected:
+ ciMethod* callee() const {
+ return _callee;
+ }
+
+ // Stack slot helpers
+ protected:
+ bool stack_slot_needs_write(int index, SharkValue* value) {
+ return value && (index < callee()->arg_size() || value->is_jobject());
+ }
+ bool stack_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject() && index >= callee()->arg_size();
+ }
+ bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
+ return index >= callee()->arg_size();
+ }
+
+ // Local slot helpers
+ protected:
+ bool local_slot_needs_write(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool local_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool local_slot_needs_debuginfo(int index, SharkValue* value) {
+ return true;
+ }
+};
+
+class SharkVMCallDecacher : public SharkDecacher {
+ public:
+ SharkVMCallDecacher(SharkFunction* function, int bci)
+ : SharkDecacher(function, bci) {}
+
+ // Stack slot helpers
+ protected:
+ bool stack_slot_needs_write(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool stack_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
+ return true;
+ }
+
+ // Local slot helpers
+ protected:
+ bool local_slot_needs_write(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool local_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool local_slot_needs_debuginfo(int index, SharkValue* value) {
+ return true;
+ }
+};
+
+class SharkTrapDecacher : public SharkDecacher {
+ public:
+ SharkTrapDecacher(SharkFunction* function, int bci)
+ : SharkDecacher(function, bci) {}
+
+ // Stack slot helpers
+ protected:
+ bool stack_slot_needs_write(int index, SharkValue* value) {
+ return value != NULL;
+ }
+ bool stack_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
+ return true;
+ }
+
+ // Local slot helpers
+ protected:
+ bool local_slot_needs_write(int index, SharkValue* value) {
+ return value != NULL;
+ }
+ bool local_slot_needs_oopmap(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+ bool local_slot_needs_debuginfo(int index, SharkValue* value) {
+ return true;
+ }
+};
+
+class SharkCacher : public SharkCacherDecacher {
+ protected:
+ SharkCacher(SharkFunction* function)
+ : SharkCacherDecacher(function) {}
+
+ // Callbacks
+ protected:
+ void process_stack_slot(int index, SharkValue** value, int offset);
+
+ void process_oop_tmp_slot(llvm::Value** value, int offset);
+ virtual void process_method_slot(llvm::Value** value, int offset);
+
+ virtual void process_local_slot(int index, SharkValue** value, int offset);
+
+ // Stack slot helper
+ protected:
+ virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0;
+
+ // Local slot helper
+ protected:
+ virtual bool local_slot_needs_read(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+
+ // Writer helper
+ protected:
+ llvm::Value* read_value_from_frame(const llvm::Type* type, int offset);
+};
+
+class SharkJavaCallCacher : public SharkCacher {
+ public:
+ SharkJavaCallCacher(SharkFunction* function, ciMethod* callee)
+ : SharkCacher(function), _callee(callee) {}
+
+ private:
+ ciMethod* _callee;
+
+ protected:
+ ciMethod* callee() const {
+ return _callee;
+ }
+
+ // Stack slot helper
+ protected:
+ bool stack_slot_needs_read(int index, SharkValue* value) {
+ return value && (index < callee()->return_type()->size() ||
+ value->is_jobject());
+ }
+};
+
+class SharkVMCallCacher : public SharkCacher {
+ public:
+ SharkVMCallCacher(SharkFunction* function)
+ : SharkCacher(function) {}
+
+ // Stack slot helper
+ protected:
+ bool stack_slot_needs_read(int index, SharkValue* value) {
+ return value && value->is_jobject();
+ }
+};
+
+class SharkFunctionEntryCacher : public SharkCacher {
+ public:
+ SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method)
+ : SharkCacher(function), _method(method) {}
+
+ private:
+ llvm::Value* _method;
+
+ private:
+ llvm::Value* method() const {
+ return _method;
+ }
+
+ // Method slot callback
+ protected:
+ void process_method_slot(llvm::Value** value, int offset);
+
+ // Stack slot helper
+ protected:
+ bool stack_slot_needs_read(int index, SharkValue* value) {
+ ShouldNotReachHere(); // entry block shouldn't have stack
+ }
+
+ // Local slot helper
+ protected:
+ bool local_slot_needs_read(int index, SharkValue* value) {
+ return value != NULL;
+ }
+};
+
+class SharkNormalEntryCacher : public SharkFunctionEntryCacher {
+ public:
+ SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method)
+ : SharkFunctionEntryCacher(function, method) {}
+};
+
+class SharkOSREntryCacher : public SharkFunctionEntryCacher {
+ public:
+ SharkOSREntryCacher(SharkFunction* function,
+ llvm::Value* method,
+ llvm::Value* osr_buf)
+ : SharkFunctionEntryCacher(function, method),
+ _osr_buf(
+ builder()->CreateBitCast(
+ osr_buf,
+ llvm::PointerType::getUnqual(
+ llvm::ArrayType::get(
+ SharkType::intptr_type(),
+ max_locals() + max_monitors() * 2)))) {}
+
+ private:
+ llvm::Value* _osr_buf;
+
+ private:
+ llvm::Value* osr_buf() const {
+ return _osr_buf;
+ }
+
+ // Callbacks
+ protected:
+ void process_monitor(int index, int box_offset, int obj_offset);
+ void process_local_slot(int index, SharkValue** value, int offset);
+
+ // Helper
+ private:
+ llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type);
+};