changeset 1492:34524a71ee10

2009-05-01 Gary Benson <gbenson@redhat.com> * ports/hotspot/src/share/vm/shark/sharkFrameCache.hpp: New file. * ports/hotspot/src/share/vm/shark/sharkFrameCache.cpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkFunction.hpp (SharkFunction::_oopmap_frame_size): Removed field. (SharkFunction::_extended_frame_size): New field. (SharkFunction::extended_frame_size): New method. (SharkFunction::oopmap_frame_size): Updated for the above. * ports/hotspot/src/share/vm/shark/sharkFunction.cpp (SharkFunction::CreateBuildFrame): Likewise. * ports/hotspot/src/share/vm/shark/sharkState.hpp (SharkState::SharkState): Remove optional method argument. (SharkState::_frame_cache): New field. (SharkState::frame_cache): New method. * ports/hotspot/src/share/vm/shark/sharkState.cpp (SharkState::SharkState): Remove optional method argument. (SharkState::initialize): Initialize frame cache. (SharkState::equal_to): Compare frame cache. (SharkState::merge): Merge frame cache. (SharkState::decache_for_Java_call): Pass frame cache. (SharkState::cache_after_Java_call): Likewise. (SharkState::decache_for_VM_call): Likewise. (SharkState::cache_after_VM_call): Likewise. (SharkState::decache_for_trap): Likewise. (SharkEntryState::SharkEntryState): Don't load initial local variables directly, populate the state with dummy values and use a SharkFunctionEntryCacher to perform the loads. * ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp (SharkCacherDecacher::SharkCacherDecacher): Remove bci argument, and add frame cache argument. (SharkCacherDecacher::_frame_cache): New field. (SharkCacherDecacher::frame_cache): New method. (SharkCacherDecacher::_bci): Removed field. (SharkCacherDecacher::bci): Removed method. (SharkDecacher::SharkDecacher): Add frame cache argument. (SharkDecacher::_bci): New field. (SharkDecacher::bci): New method. (SharkDecacher::write_value_to_frame): New method. (SharkJavaCallDecacher::SharkJavaCallDecacher): Add frame cache. (SharkVMCallDecacher::SharkVMCallDecacher): Likewise. (SharkTrapDecacher::SharkTrapDecacher): Likewise. (SharkCacher::SharkCacher): Likewise. (SharkDecacher::process_method_slot): Made virtual. (SharkDecacher::local_slot_needs_read): Likewise. (SharkDecacher::read_value_from_frame): New method. (SharkJavaCallCacher::SharkJavaCallDecacher): Add frame cache. (SharkVMCallCacher::SharkVMCallDecacher): Likewise. (SharkFunctionEntryCacher): New class. * ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp (SharkDecacher::process_stack_slot): Use write_value_to_frame. (SharkDecacher::process_method_slot): Likewise. (SharkDecacher::process_local_slot): Likewise. (SharkCacher::process_stack_slot): Use read_value_from_frame. (SharkCacher::process_method_slot): Likewise. (SharkCacher::process_local_slot): Likewise. (SharkFunctionEntryCacher::process_method_slot): New method. (SharkDecacher::write_value_to_frame): Likewise. (SharkDecacher::read_value_from_frame): Likewise. * ports/hotspot/src/share/vm/includeDB_shark: Updated.
author Gary Benson <gbenson@redhat.com>
date Fri, 01 May 2009 05:17:26 -0400
parents afe7df786dd4
children 868030b86280
files ChangeLog ports/hotspot/src/share/vm/includeDB_shark ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp ports/hotspot/src/share/vm/shark/sharkFrameCache.cpp ports/hotspot/src/share/vm/shark/sharkFrameCache.hpp ports/hotspot/src/share/vm/shark/sharkFunction.cpp ports/hotspot/src/share/vm/shark/sharkFunction.hpp ports/hotspot/src/share/vm/shark/sharkState.cpp ports/hotspot/src/share/vm/shark/sharkState.hpp
diffstat 10 files changed, 408 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Apr 30 16:31:55 2009 -0400
+++ b/ChangeLog	Fri May 01 05:17:26 2009 -0400
@@ -1,3 +1,68 @@
+2009-05-01  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/share/vm/shark/sharkFrameCache.hpp: New file.
+	* ports/hotspot/src/share/vm/shark/sharkFrameCache.cpp: Likewise.
+
+	* ports/hotspot/src/share/vm/shark/sharkFunction.hpp
+	(SharkFunction::_oopmap_frame_size): Removed field.
+	(SharkFunction::_extended_frame_size): New field.
+	(SharkFunction::extended_frame_size): New method.
+	(SharkFunction::oopmap_frame_size): Updated for the above.
+	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp
+	(SharkFunction::CreateBuildFrame): Likewise.
+
+	* ports/hotspot/src/share/vm/shark/sharkState.hpp
+	(SharkState::SharkState): Remove optional method argument.
+	(SharkState::_frame_cache): New field.
+	(SharkState::frame_cache): New method.
+	* ports/hotspot/src/share/vm/shark/sharkState.cpp
+	(SharkState::SharkState): Remove optional method argument.
+	(SharkState::initialize): Initialize frame cache.
+	(SharkState::equal_to): Compare frame cache.
+	(SharkState::merge): Merge frame cache.
+	(SharkState::decache_for_Java_call): Pass frame cache.
+	(SharkState::cache_after_Java_call): Likewise.
+	(SharkState::decache_for_VM_call): Likewise.
+	(SharkState::cache_after_VM_call): Likewise.
+	(SharkState::decache_for_trap): Likewise.
+	(SharkEntryState::SharkEntryState): Don't load initial local
+	variables directly, populate the state with dummy values and
+	use a SharkFunctionEntryCacher to perform the loads.
+
+	* ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp
+	(SharkCacherDecacher::SharkCacherDecacher): Remove bci argument,
+	and add frame cache argument.
+	(SharkCacherDecacher::_frame_cache): New field.
+	(SharkCacherDecacher::frame_cache): New method.
+	(SharkCacherDecacher::_bci): Removed field.
+	(SharkCacherDecacher::bci): Removed method.
+	(SharkDecacher::SharkDecacher): Add frame cache argument.
+	(SharkDecacher::_bci): New field.
+	(SharkDecacher::bci): New method.
+	(SharkDecacher::write_value_to_frame): New method.
+	(SharkJavaCallDecacher::SharkJavaCallDecacher): Add frame cache.
+	(SharkVMCallDecacher::SharkVMCallDecacher): Likewise.
+	(SharkTrapDecacher::SharkTrapDecacher): Likewise.
+	(SharkCacher::SharkCacher): Likewise.
+	(SharkDecacher::process_method_slot): Made virtual.
+	(SharkDecacher::local_slot_needs_read): Likewise.
+	(SharkDecacher::read_value_from_frame): New method.
+	(SharkJavaCallCacher::SharkJavaCallDecacher): Add frame cache.
+	(SharkVMCallCacher::SharkVMCallDecacher): Likewise.
+	(SharkFunctionEntryCacher): New class.
+	* ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp
+	(SharkDecacher::process_stack_slot): Use write_value_to_frame.
+	(SharkDecacher::process_method_slot): Likewise.
+	(SharkDecacher::process_local_slot): Likewise.
+	(SharkCacher::process_stack_slot): Use read_value_from_frame.
+	(SharkCacher::process_method_slot): Likewise.
+	(SharkCacher::process_local_slot): Likewise.
+	(SharkFunctionEntryCacher::process_method_slot): New method.
+	(SharkDecacher::write_value_to_frame): Likewise.
+	(SharkDecacher::read_value_from_frame): Likewise.
+
+	* ports/hotspot/src/share/vm/includeDB_shark: Updated.
+
 2009-04-30 Deepak Bhole <dbhole@redhat.com>
 
 	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Forgo
--- a/ports/hotspot/src/share/vm/includeDB_shark	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/includeDB_shark	Fri May 01 05:17:26 2009 -0400
@@ -117,12 +117,14 @@
 sharkCacheDecache.cpp                   llvmValue.hpp
 sharkCacheDecache.cpp                   sharkBuilder.hpp
 sharkCacheDecache.cpp                   sharkCacheDecache.hpp
+sharkCacheDecache.cpp                   sharkFrameCache.hpp
 sharkCacheDecache.cpp                   sharkFunction.hpp
 sharkCacheDecache.cpp                   sharkState.inline.hpp
 
 sharkCacheDecache.hpp                   ciMethod.hpp
 sharkCacheDecache.hpp                   debugInfoRec.hpp
 sharkCacheDecache.hpp                   sharkBuilder.hpp
+sharkCacheDecache.hpp                   sharkFrameCache.hpp
 sharkCacheDecache.hpp                   sharkFunction.hpp
 sharkCacheDecache.hpp                   sharkStateScanner.hpp
 
@@ -173,6 +175,15 @@
 
 sharkEntry.hpp                          llvmHeaders.hpp
 
+sharkFrameCache.cpp                     allocation.hpp
+sharkFrameCache.cpp                     llvmHeaders.hpp
+sharkFrameCache.cpp                     sharkFrameCache.hpp
+sharkFrameCache.cpp                     sharkFunction.hpp
+
+sharkFrameCache.hpp                     allocation.hpp
+sharkFrameCache.hpp                     llvmHeaders.hpp
+sharkFrameCache.hpp                     sharkFunction.hpp
+
 sharkFunction.cpp                       allocation.hpp
 sharkFunction.cpp                       ciTypeFlow.hpp
 sharkFunction.cpp                       debug.hpp
@@ -263,6 +274,7 @@
 sharkState.cpp                          ciTypeFlow.hpp
 sharkState.cpp                          sharkBuilder.hpp
 sharkState.cpp                          sharkCacheDecache.hpp
+sharkState.cpp                          sharkFrameCache.hpp
 sharkState.cpp                          sharkState.inline.hpp
 sharkState.cpp                          sharkTopLevelBlock.hpp
 sharkState.cpp                          sharkType.hpp
@@ -272,6 +284,7 @@
 sharkState.hpp                          ciMethod.hpp
 sharkState.hpp                          llvmHeaders.hpp
 sharkState.hpp                          sharkBuilder.hpp
+sharkState.hpp                          sharkFrameCache.hpp
 sharkState.hpp                          sharkValue.hpp
 
 sharkState.inline.hpp                   sharkBlock.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkCacheDecache.cpp	Fri May 01 05:17:26 2009 -0400
@@ -59,11 +59,10 @@
 
   // Write the value to the frame if necessary
   if (stack_slot_needs_write(index, value)) {
-    builder()->CreateStore(
+    write_value_to_frame(
+      SharkType::to_stackType(value->basic_type()),
       value->generic_value(),
-      function()->CreateAddressOfFrameEntry(
-        adjusted_offset(value, offset),
-        SharkType::to_stackType(value->basic_type())));
+      adjusted_offset(value, offset));
   }
 
   // Record the value in the oopmap if necessary
@@ -104,11 +103,11 @@
 void SharkDecacher::process_method_slot(llvm::Value** value, int offset)
 {
   // Decache the method pointer
-  builder()->CreateStore(
+  write_value_to_frame(
+    SharkType::methodOop_type(),
     *value,
-    function()->CreateAddressOfFrameEntry(
-      offset,
-      SharkType::methodOop_type()));
+    offset);
+
   oopmap()->set_oop(slot2reg(offset));  
 }
 
@@ -134,11 +133,10 @@
 
   // Write the value to the frame if necessary
   if (local_slot_needs_write(index, value)) {
-    builder()->CreateStore(
+    write_value_to_frame(
+      SharkType::to_stackType(value->basic_type()),
       value->generic_value(),
-      function()->CreateAddressOfFrameEntry(
-        adjusted_offset(value, offset),
-        SharkType::to_stackType(value->basic_type())));
+      adjusted_offset(value, offset));
   }
 
   // Record the value in the oopmap if necessary
@@ -177,10 +175,9 @@
   if (stack_slot_needs_read(index, value)) {
     *addr = SharkValue::create_generic(
       value->type(),
-      builder()->CreateLoad(
-        function()->CreateAddressOfFrameEntry(
-          adjusted_offset(value, offset),
-          SharkType::to_stackType(value->basic_type()))),
+      read_value_from_frame(
+        SharkType::to_stackType(value->basic_type()),
+        adjusted_offset(value, offset)),
       value->zero_checked());
   }
 }
@@ -188,10 +185,14 @@
 void SharkCacher::process_method_slot(llvm::Value** value, int offset)
 {
   // Cache the method pointer
-  *value = builder()->CreateLoad(
-    function()->CreateAddressOfFrameEntry(
-      offset,
-      SharkType::methodOop_type()));
+  *value = read_value_from_frame(SharkType::methodOop_type(), offset);
+}
+
+void SharkFunctionEntryCacher::process_method_slot(llvm::Value** value,
+                                                   int           offset)
+{
+  // "Cache" the method pointer
+  *value = method();
 }
 
 void SharkCacher::process_local_slot(int          index,
@@ -204,10 +205,28 @@
   if (local_slot_needs_read(index, value)) {
     *addr = SharkValue::create_generic(
       value->type(),
-      builder()->CreateLoad(
-        function()->CreateAddressOfFrameEntry(
-          adjusted_offset(value, offset),
-          SharkType::to_stackType(value->basic_type()))),
+      read_value_from_frame(
+        SharkType::to_stackType(value->basic_type()),
+        adjusted_offset(value, offset)),
       value->zero_checked());
   }
 }
+
+void SharkDecacher::write_value_to_frame(const llvm::Type* type,
+                                         llvm::Value*      value,
+                                         int               offset)
+{
+  if (frame_cache()->value(offset) != value) {
+    builder()->CreateStore(
+      value,
+      function()->CreateAddressOfFrameEntry(offset, type));
+  }
+}
+
+Value* SharkCacher::read_value_from_frame(const llvm::Type* type, int offset)
+{
+  Value *result = builder()->CreateLoad(
+    function()->CreateAddressOfFrameEntry(offset, type));
+  frame_cache()->set_value(offset, result);
+  return result;
+}
--- a/ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkCacheDecache.hpp	Fri May 01 05:17:26 2009 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
- * Copyright 2008 Red Hat, Inc.
+ * 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
@@ -33,11 +33,21 @@
 //     - SharkCacher
 //       - SharkJavaCallCacher
 //       - SharkVMCallCacher
+//       - SharkFunctionEntryCacher
 
 class SharkCacherDecacher : public SharkStateScanner {
  protected:
-  SharkCacherDecacher(SharkFunction* function, int bci)
-    : SharkStateScanner(function), _bci(bci) {}
+  SharkCacherDecacher(SharkFunction* function, SharkFrameCache* frame_cache)
+    : SharkStateScanner(function), _frame_cache(frame_cache) {}
+
+ private:
+  SharkFrameCache* _frame_cache;
+
+ protected:
+  SharkFrameCache* frame_cache() const
+  {
+    return _frame_cache;
+  }
 
  protected:
   SharkBuilder* builder() const
@@ -45,15 +55,6 @@
     return function()->builder();
   }  
 
- private:
-  int _bci;
-  
- protected:
-  int bci() const
-  {
-    return _bci;
-  }
-
   // Helper
  protected:
   static int adjusted_offset(SharkValue* value, int offset)
@@ -66,8 +67,17 @@
 
 class SharkDecacher : public SharkCacherDecacher {
  protected:
-  SharkDecacher(SharkFunction* function, int bci)
-    : SharkCacherDecacher(function, bci) {}
+  SharkDecacher(SharkFunction* function, SharkFrameCache* frame_cache, int bci)
+    : SharkCacherDecacher(function, frame_cache), _bci(bci) {}
+
+ private:
+  int _bci;
+  
+ protected:
+  int bci() const
+  {
+    return _bci;
+  }
 
  private:
   DebugInformationRecorder* debug_info() const
@@ -171,12 +181,21 @@
       return Location::normal;
     return Location::invalid;
   }
+
+  // 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) {}
+  SharkJavaCallDecacher(SharkFunction*   function,
+                        SharkFrameCache* frame_cache,
+                        int              bci,
+                        ciMethod*        callee)
+    : SharkDecacher(function, frame_cache, bci), _callee(callee) {}
 
  private:
   ciMethod* _callee;
@@ -220,8 +239,10 @@
 
 class SharkVMCallDecacher : public SharkDecacher {
  public:
-  SharkVMCallDecacher(SharkFunction* function, int bci)
-    : SharkDecacher(function, bci) {}
+  SharkVMCallDecacher(SharkFunction*   function,
+                      SharkFrameCache* frame_cache,
+                      int              bci)
+    : SharkDecacher(function, frame_cache, bci) {}
 
   // Stack slot helpers
  protected:
@@ -256,8 +277,10 @@
 
 class SharkTrapDecacher : public SharkDecacher {
  public:
-  SharkTrapDecacher(SharkFunction* function, int bci)
-    : SharkDecacher(function, bci) {}
+  SharkTrapDecacher(SharkFunction*   function,
+                    SharkFrameCache* frame_cache,
+                    int              bci)
+    : SharkDecacher(function, frame_cache, bci) {}
 
   // Stack slot helpers
  protected:
@@ -292,14 +315,14 @@
 
 class SharkCacher : public SharkCacherDecacher {
  protected:
-  SharkCacher(SharkFunction* function, int bci)
-    : SharkCacherDecacher(function, bci) {}
+  SharkCacher(SharkFunction* function, SharkFrameCache* frame_cache)
+    : SharkCacherDecacher(function, frame_cache) {}
 
   // Callbacks
  protected:
   void process_stack_slot(int index, SharkValue** value, int offset);
 
-  void process_method_slot(llvm::Value** value, int offset);
+  virtual void process_method_slot(llvm::Value** value, int offset);
 
   void process_local_slot(int index, SharkValue** value, int offset);
 
@@ -309,16 +332,22 @@
 
   // Local slot helper
  protected:
-  bool local_slot_needs_read(int index, SharkValue* value)
+  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, int bci, ciMethod* callee)
-    : SharkCacher(function, bci), _callee(callee) {}
+  SharkJavaCallCacher(SharkFunction*   function,
+                      SharkFrameCache* frame_cache,
+                      ciMethod*        callee)
+    : SharkCacher(function, frame_cache), _callee(callee) {}
 
  private:
   ciMethod* _callee;
@@ -340,8 +369,8 @@
 
 class SharkVMCallCacher : public SharkCacher {
  public:
-  SharkVMCallCacher(SharkFunction* function, int bci)
-    : SharkCacher(function, bci) {}
+  SharkVMCallCacher(SharkFunction* function, SharkFrameCache* frame_cache)
+    : SharkCacher(function, frame_cache) {}
 
   // Stack slot helper
  protected:
@@ -350,3 +379,38 @@
     return value && value->is_jobject();
   }
 };
+
+class SharkFunctionEntryCacher : public SharkCacher {
+ public:
+  SharkFunctionEntryCacher(SharkFunction*   function,
+                           SharkFrameCache* frame_cache,
+                           llvm::Value*     method)
+    : SharkCacher(function, frame_cache), _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:
+  virtual bool local_slot_needs_read(int index, SharkValue* value)
+  {
+    return value != NULL;
+  }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkFrameCache.cpp	Fri May 01 05:17:26 2009 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include "incls/_precompiled.incl"
+#include "incls/_sharkFrameCache.cpp.incl"
+
+using namespace llvm;
+
+SharkFrameCache::SharkFrameCache(SharkFunction *function)
+  : _frame_size(function->extended_frame_size())
+{
+  _values = NEW_RESOURCE_ARRAY(Value*, frame_size());
+  memset(_values, 0, frame_size() * sizeof(Value *));
+}
+
+SharkFrameCache::SharkFrameCache(const SharkFrameCache* cache)
+  : _frame_size(cache->frame_size())
+{
+  _values = NEW_RESOURCE_ARRAY(Value*, frame_size());
+  memcpy(_values, cache->_values, frame_size() * sizeof(Value *));
+}
+
+bool SharkFrameCache::equal_to(SharkFrameCache* other)
+{
+  if (frame_size() != other->frame_size())
+    return false;
+
+  for (int i = 0; i < frame_size(); i++) {
+    if (value(i) != other->value(i))
+      return false;
+  }
+
+  return true;
+}
+
+void SharkFrameCache::merge(SharkFrameCache* other)
+{
+  assert(frame_size() == other->frame_size(), "should be");
+
+  for (int i = 0; i < frame_size(); i++) {
+    if (value(i) != other->value(i))
+      set_value(i, NULL);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkFrameCache.hpp	Fri May 01 05:17:26 2009 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+class SharkFrameCache : public ResourceObj {
+ public:
+  SharkFrameCache(SharkFunction* function);
+
+ protected:
+  SharkFrameCache(const SharkFrameCache* cache);
+
+ private:
+  int           _frame_size;
+  llvm::Value** _values;
+
+ private:
+  int frame_size() const
+  {
+    return _frame_size;
+  }
+
+ public:
+  llvm::Value* value(int slot)
+  {
+    assert(slot >= 0 && slot < frame_size(), "bad index");
+    return _values[slot];
+  }
+  void set_value(int slot, llvm::Value* value)
+  {
+    assert(slot >= 0 && slot < frame_size(), "bad index");
+    _values[slot] = value;
+  }
+
+  // Comparison
+ public:
+  bool equal_to(SharkFrameCache* other);
+
+  // Copy and merge
+ public:
+  SharkFrameCache *copy() const
+  {
+    return new SharkFrameCache(this);
+  }
+  void merge(SharkFrameCache* other);
+};
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Fri May 01 05:17:26 2009 -0400
@@ -220,7 +220,7 @@
   int stack_words   = max_stack();
   int frame_words   = header_words + monitor_words + stack_words;
 
-  _oopmap_frame_size = frame_words + extra_locals;
+  _extended_frame_size = frame_words + locals_words;
 
   // Update the stack pointer
   Value *zero_stack_pointer = builder()->CreateSub(
@@ -233,7 +233,7 @@
   _frame = builder()->CreateIntToPtr(
     zero_stack_pointer,
     PointerType::getUnqual(
-      ArrayType::get(SharkType::intptr_type(), frame_words + locals_words)),
+      ArrayType::get(SharkType::intptr_type(), extended_frame_size())),
     "frame");
   int offset = 0;
 
@@ -277,7 +277,7 @@
   _locals_slots_offset = offset;  
   offset += locals_words;
 
-  assert(offset == frame_words + locals_words, "should do");
+  assert(offset == extended_frame_size(), "should do");
   return fp;
 }
 
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Fri May 01 05:17:26 2009 -0400
@@ -253,7 +253,7 @@
   }
 
  private:
-  int _oopmap_frame_size;
+  int _extended_frame_size;
   int _stack_slots_offset;
   int _monitors_slots_offset;
   int _exception_slot_offset;
@@ -262,9 +262,13 @@
   int _locals_slots_offset;
 
  public:
+  int extended_frame_size() const
+  {
+    return _extended_frame_size;
+  }
   int oopmap_frame_size() const
   {
-    return _oopmap_frame_size;
+    return extended_frame_size() - arg_size();
   }
   int stack_slots_offset() const
   {
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp	Fri May 01 05:17:26 2009 -0400
@@ -28,12 +28,11 @@
 
 using namespace llvm;
 
-SharkState::SharkState(SharkBlock*    block,
-                       SharkFunction* function,
-                       llvm::Value*   method)
+SharkState::SharkState(SharkBlock* block, SharkFunction* function)
   : _block(block),
     _function(function),
-    _method(method)
+    _method(NULL),
+    _frame_cache(NULL)
 {
   initialize(NULL);
 }
@@ -41,7 +40,8 @@
 SharkState::SharkState(SharkBlock* block, const SharkState* state)
   : _block(block),
     _function(state->function()),
-    _method(state->method())
+    _method(state->method()),
+    _frame_cache(NULL)
 {
   initialize(state);
 }
@@ -69,7 +69,13 @@
         value = value->clone();
       push(value);
     }
+
+    if (state->frame_cache())
+      _frame_cache = state->frame_cache()->copy();
   } 
+  else if (function()) {
+    _frame_cache = new SharkFrameCache(function());
+  }
 }
 
 bool SharkState::equal_to(SharkState *other)
@@ -89,6 +95,7 @@
   if (stack_depth() != other->stack_depth())
     return false;
 
+  // Local variables
   for (int i = 0; i < max_locals(); i++) {
     SharkValue *value = local(i);
     SharkValue *other_value = other->local(i);
@@ -106,6 +113,7 @@
     }
   }
 
+  // Expression stack
   for (int i = 0; i < stack_depth(); i++) {
     SharkValue *value = stack(i);
     SharkValue *other_value = other->stack(i);
@@ -123,6 +131,19 @@
     }
   }
 
+  // Frame cache
+  if (frame_cache() == NULL) {
+    if (other->frame_cache() != NULL)
+      return false;
+  }
+  else {
+    if (other->frame_cache() == NULL)
+      return false;
+
+    if (!frame_cache()->equal_to(other->frame_cache()))
+      return false;
+  }
+
   return true;
 }
 
@@ -167,12 +188,16 @@
         builder(), other_value, other_block, this_block, name));
     }
   }
+
+  // Frame cache
+  frame_cache()->merge(other->frame_cache());
 }
 
 void SharkState::decache_for_Java_call(ciMethod* callee)
 {
   assert(function() && method(), "you cannot decache here");
-  SharkJavaCallDecacher(function(), block()->bci(), callee).scan(this);
+  SharkJavaCallDecacher(
+    function(), frame_cache(), block()->bci(), callee).scan(this);
   pop(callee->arg_size());
 }
 
@@ -197,31 +222,31 @@
     if (type->is_two_word())
       push(NULL);
   }
-  SharkJavaCallCacher(function(), block()->bci(), callee).scan(this);
+  SharkJavaCallCacher(function(), frame_cache(), callee).scan(this);
 }
 
 void SharkState::decache_for_VM_call()
 {
   assert(function() && method(), "you cannot decache here");
-  SharkVMCallDecacher(function(), block()->bci()).scan(this);
+  SharkVMCallDecacher(function(), frame_cache(), block()->bci()).scan(this);
 }
 
 void SharkState::cache_after_VM_call()
 {
   assert(function() && method(), "you cannot cache here");
-  SharkVMCallCacher(function(), block()->bci()).scan(this);
+  SharkVMCallCacher(function(), frame_cache()).scan(this);
 }
 
 void SharkState::decache_for_trap()
 {
   assert(function() && method(), "you cannot decache here");
-  SharkTrapDecacher(function(), block()->bci()).scan(this);
+  SharkTrapDecacher(function(), frame_cache(), block()->bci()).scan(this);
 }
 
 SharkEntryState::SharkEntryState(SharkTopLevelBlock* block, Value* method)
-  : SharkState(block, block->function(), method)
+  : SharkState(block, block->function())
 {
-  char name[18];
+  assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
 
   // Local variables
   for (int i = 0; i < max_locals(); i++) {
@@ -235,21 +260,11 @@
     case T_DOUBLE:
     case T_OBJECT:
     case T_ARRAY:
-      if (i < function()->arg_size()) {
-        snprintf(name, sizeof(name), "local_%d_", i);
-        value = SharkValue::create_generic(
-          type,
-          builder()->CreateLoad(
-            function()->CreateAddressOfFrameEntry(
-              function()->locals_slots_offset()
-              + max_locals() - type->size() - i,
-              SharkType::to_stackType(type)),
-            name),
-          i == 0 && !function()->target()->is_static());
+      if (i >= function()->arg_size()) {
+        ShouldNotReachHere();
       }
-      else {
-        Unimplemented();
-      }
+      value = SharkValue::create_generic(
+        type, NULL, i == 0 && !function()->target()->is_static());
       break;
     
     case ciTypeFlow::StateVector::T_BOTTOM:
@@ -264,9 +279,7 @@
     }
     set_local(i, value);
   }
-
-  // Expression stack
-  assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
+  SharkFunctionEntryCacher(function(), frame_cache(), method).scan(this);  
 }
 
 SharkPHIState::SharkPHIState(SharkTopLevelBlock* block)
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp	Thu Apr 30 16:31:55 2009 -0400
+++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp	Fri May 01 05:17:26 2009 -0400
@@ -29,21 +29,20 @@
 
 class SharkState : public ResourceObj {
  public:
-  SharkState(SharkBlock*    block,
-             SharkFunction* function = NULL,
-             llvm::Value*   method = NULL);
+  SharkState(SharkBlock* block, SharkFunction* function = NULL);
   SharkState(SharkBlock* block, const SharkState* state);
 
  private:
   void initialize(const SharkState* state);
 
  private:
-  SharkBlock*    _block;
-  SharkFunction* _function;
-  llvm::Value*   _method;
-  SharkValue**   _locals;
-  SharkValue**   _stack;
-  SharkValue**   _sp;
+  SharkBlock*      _block;
+  SharkFunction*   _function;
+  llvm::Value*     _method;
+  SharkFrameCache* _frame_cache;
+  SharkValue**     _locals;
+  SharkValue**     _stack;
+  SharkValue**     _sp;
 
  public:
   SharkBlock *block() const
@@ -54,6 +53,10 @@
   {
     return _function;
   }
+  SharkFrameCache *frame_cache() const
+  {
+    return _frame_cache;
+  }
   
  public:
   inline SharkBuilder* builder() const;