changeset 17379:21015ffe0a1e

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 09 Oct 2014 00:23:17 +0200
parents d42e11af980d (current diff) b888ded3ee42 (diff)
children 4b94e5f3d823 538cbc117324
files
diffstat 13 files changed, 211 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl	Thu Oct 09 00:20:30 2014 +0200
+++ b/graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl	Thu Oct 09 00:23:17 2014 +0200
@@ -18,9 +18,12 @@
 }
 
 function main() {
+    originalMaxCallerSize = getOption("TruffleInliningMaxCallerSize");
+    setOption("TruffleInliningMaxCallerSize", 20);
     waitForOptimization(callUntilOptimized(test1));
     assertTrue(isInlined(test1, test1, inlinableFunction), "inlinableFunction is not inlined");
     
     waitForOptimization(callUntilOptimized(test2));
     assertFalse(isInlined(test2, test2, notInlinableFunction), "notInlinableFunction is inlined");
+    setOption("TruffleInliningMaxCallerSize", originalMaxCallerSize);
 }  
--- a/src/share/vm/code/debugInfoRec.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/code/debugInfoRec.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -37,6 +37,9 @@
   int  _offset; // location in the stream of this scope
   int  _length; // number of bytes in the stream
   int  _hash;   // hash of stream bytes (for quicker reuse)
+#ifdef GRAAL
+  DebugInformationRecorder* _DIR;
+#endif
 
   void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() {
     assert(ignore == sizeof(DIR_Chunk), "");
@@ -51,6 +54,9 @@
   DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) {
     _offset = offset;
     _length = length;
+#ifdef GRAAL
+    _DIR = dir;
+#endif
     unsigned int hash = 0;
     address p = dir->stream()->buffer() + _offset;
     for (int i = 0; i < length; i++) {
@@ -77,6 +83,25 @@
     }
     return NULL;
   }
+
+#ifdef GRAAL
+  static int compare(DIR_Chunk* a, DIR_Chunk* b) {
+    if (b->_hash > a->_hash) {
+      return 1;
+    }
+    if (b->_hash < a->_hash) {
+      return -1;
+    }
+    if (b->_length > a->_length) {
+      return 1;
+    }
+    if (b->_length < a->_length) {
+      return -1;
+    }
+    address buf = a->_DIR->stream()->buffer();
+    return memcmp(buf + b->_offset, buf + a->_offset, a->_length);
+  }
+#endif
 };
 
 static inline bool compute_recording_non_safepoints() {
@@ -113,7 +138,9 @@
   _oop_recorder = oop_recorder;
 
   _all_chunks    = new GrowableArray<DIR_Chunk*>(300);
+#ifndef GRAAL
   _shared_chunks = new GrowableArray<DIR_Chunk*>(30);
+#endif
   _next_chunk = _next_chunk_limit = NULL;
 
   add_new_pc_offset(PcDesc::lower_offset_limit);  // sentinel record
@@ -250,6 +277,19 @@
 
   DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this);
 
+#ifdef GRAAL
+  DIR_Chunk* match = _all_chunks->find_insert_binary<DIR_Chunk::compare>(ns);
+  if (match != ns) {
+    // Found an existing chunk
+    NOT_PRODUCT(++dir_stats.chunks_shared);
+    assert(ns+1 == _next_chunk, "");
+    _next_chunk = ns;
+    return match->_offset;
+  } else {
+    // Inserted this chunk, so nothing to do
+    return serialized_null;
+  }
+#else
   // Look in previously shared scopes first:
   DIR_Chunk* ms = ns->find_match(_shared_chunks, 0, this);
   if (ms != NULL) {
@@ -277,6 +317,7 @@
   // No match.  Add this guy to the list, in hopes of future shares.
   _all_chunks->append(ns);
   return serialized_null;
+#endif
 }
 
 
--- a/src/share/vm/code/debugInfoRec.hpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/code/debugInfoRec.hpp	Thu Oct 09 00:23:17 2014 +0200
@@ -163,7 +163,9 @@
 
   // Scopes that have been described so far.
   GrowableArray<DIR_Chunk*>* _all_chunks;
+#ifndef GRAAL
   GrowableArray<DIR_Chunk*>* _shared_chunks;
+#endif
   DIR_Chunk* _next_chunk;
   DIR_Chunk* _next_chunk_limit;
 
--- a/src/share/vm/code/nmethod.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/code/nmethod.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -1044,12 +1044,13 @@
     LOG_OFFSET(xtty, consts);
     LOG_OFFSET(xtty, insts);
     LOG_OFFSET(xtty, stub);
+    LOG_OFFSET(xtty, oops);
+    LOG_OFFSET(xtty, metadata);
     LOG_OFFSET(xtty, scopes_data);
     LOG_OFFSET(xtty, scopes_pcs);
     LOG_OFFSET(xtty, dependencies);
     LOG_OFFSET(xtty, handler_table);
     LOG_OFFSET(xtty, nul_chk_table);
-    LOG_OFFSET(xtty, oops);
 
     xtty->method(method());
     xtty->stamp();
--- a/src/share/vm/code/oopRecorder.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/code/oopRecorder.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -34,9 +34,17 @@
 template <class T> int ValueRecorder<T>::_find_index_calls = 0;
 template <class T> int ValueRecorder<T>::_hit_indexes      = 0;
 template <class T> int ValueRecorder<T>::_missed_indexes   = 0;
+
+void OopRecorder::check_for_duplicates(int index, jobject h) {
+  oop o = JNIHandles::resolve(h);
+  for (int i = 1; i < oop_count(); i++) {
+    if (o == JNIHandles::resolve(oop_at(i)) && index != i) {
+      assert(false, "duplicate found");
+    }
+  }
+}
 #endif //ASSERT
 
-
 template <class T> ValueRecorder<T>::ValueRecorder(Arena* arena) {
   _handles  = NULL;
   _indexes  = NULL;
@@ -157,3 +165,49 @@
 // Explicitly instantiate these types
 template class ValueRecorder<Metadata*>;
 template class ValueRecorder<jobject>;
+
+oop ObjectLookup::ObjectEntry::oop_value() { return JNIHandles::resolve(_value); }
+
+ObjectLookup::ObjectLookup(): _gc_count(Universe::heap()->total_collections()), _values(4) {}
+
+void ObjectLookup::maybe_resort() {
+  // The values are kept sorted by address which may be invalidated
+  // after a GC, so resort if a GC has occurred since last time.
+  if (_gc_count != Universe::heap()->total_collections()) {
+    _gc_count = Universe::heap()->total_collections();
+    _values.sort(sort_by_address);
+  }
+}
+
+int ObjectLookup::sort_by_address(oop a, oop b) {
+  if (b > a) return 1;
+  if (a > b) return -1;
+  return 0;
+}
+
+int ObjectLookup::sort_by_address(ObjectEntry* a, ObjectEntry* b) {
+  return sort_by_address(a->oop_value(), b->oop_value());
+}
+
+int ObjectLookup::sort_oop_by_address(oop a, ObjectEntry b) {
+  return sort_by_address(a, b.oop_value());
+}
+  
+int ObjectLookup::find_index(jobject handle, OopRecorder* oop_recorder) {
+  if (handle == NULL) {
+    return 0;
+  }
+  oop object = JNIHandles::resolve(handle);
+  maybe_resort();
+  bool found;
+  int location = _values.find_binary<oop, sort_oop_by_address>(object, found);
+  if (!found) {
+    assert(location <= _values.length(), "out of range");
+    jobject handle = JNIHandles::make_local(object);
+    ObjectEntry r(handle, oop_recorder->allocate_oop_index(handle));
+    _values.insert_binary(location, r);
+    return r.index();
+  }
+  return _values.at(location).index();
+}
+
--- a/src/share/vm/code/oopRecorder.hpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/code/oopRecorder.hpp	Thu Oct 09 00:23:17 2014 +0200
@@ -146,18 +146,61 @@
 #endif
 };
 
+class OopRecorder;
+
+class ObjectLookup : public ResourceObj {
+ private:
+  class ObjectEntry {
+   private:
+    jobject _value;
+    int     _index;
+
+   public:
+    ObjectEntry(jobject value, int index): _value(value), _index(index) {}
+    ObjectEntry() {}
+    oop oop_value(); // { return JNIHandles::resolve(_value); }
+    int index() { return _index; }
+  };
+
+  GrowableArray<ObjectEntry> _values;
+  unsigned int _gc_count;
+
+  // Utility sort functions
+  static int sort_by_address(oop a, oop b);
+  static int sort_by_address(ObjectEntry* a, ObjectEntry* b);
+  static int sort_oop_by_address(oop a, ObjectEntry b);
+
+ public:
+  ObjectLookup();
+  
+  // Resort list if a GC has occurred since the last sort
+  void maybe_resort();
+  int find_index(jobject object, OopRecorder* oop_recorder);
+};
+
 class OopRecorder : public ResourceObj {
  private:
   ValueRecorder<jobject>      _oops;
   ValueRecorder<Metadata*>    _metadata;
+  ObjectLookup*               _object_lookup;
  public:
-  OopRecorder(Arena* arena = NULL): _oops(arena), _metadata(arena) {}
+  OopRecorder(Arena* arena = NULL, bool deduplicate = false): _oops(arena), _metadata(arena) {
+    if (deduplicate) {
+      _object_lookup = new ObjectLookup();
+    } else {
+      _object_lookup = NULL;
+    }
+  }
+
+  void check_for_duplicates(int index, jobject h) NOT_DEBUG_RETURN;
 
   int allocate_oop_index(jobject h) {
     return _oops.allocate_index(h);
   }
   int find_index(jobject h) {
-    return _oops.find_index(h);
+    int result = _object_lookup != NULL ? _object_lookup->find_index(h, this) : _oops.find_index(h);
+    check_for_duplicates(result, h);
+    return result;
   }
   jobject oop_at(int index) {
     return _oops.at(index);
--- a/src/share/vm/compiler/compileBroker.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -2381,6 +2381,7 @@
                 stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count,
                 stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count,
                 stats->_nmethods_size, stats->_nmethods_code_size);
+  comp->print_timers();
 }
 #endif
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -370,7 +370,7 @@
 }
 
 void CodeInstaller::initialize_assumptions(oop compiled_code) {
-  _oop_recorder = new OopRecorder(&_arena);
+  _oop_recorder = new OopRecorder(&_arena, true);
   _dependencies = new Dependencies(&_arena, _oop_recorder);
   Handle assumptions_handle = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code));
   if (!assumptions_handle.is_null()) {
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -31,6 +31,7 @@
 #include "runtime/globals_extension.hpp"
 
 GraalCompiler* GraalCompiler::_instance = NULL;
+elapsedTimer GraalCompiler::_codeInstallTimer;
 
 GraalCompiler::GraalCompiler() : AbstractCompiler(graal) {
 #ifdef COMPILERGRAAL
@@ -152,6 +153,7 @@
 // Print compilation timers and statistics
 void GraalCompiler::print_timers() {
   TRACE_graal_1("GraalCompiler::print_timers");
+  tty->print_cr("       Graal code install time:        %6.3f s",    _codeInstallTimer.seconds());
 }
 
 #endif // COMPILERGRAAL
--- a/src/share/vm/graal/graalCompiler.hpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/graal/graalCompiler.hpp	Thu Oct 09 00:23:17 2014 +0200
@@ -43,6 +43,8 @@
 
   static GraalCompiler* _instance;
  
+  static elapsedTimer _codeInstallTimer;
+
 public:
 
   GraalCompiler();
@@ -79,6 +81,8 @@
   void reset_compilation_stats();
 #endif // COMPILERGRAAL
 
+  static elapsedTimer* codeInstallTimer() { return &_codeInstallTimer; }
+
 #ifndef PRODUCT
   void compile_the_world();
 #endif
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -454,6 +454,7 @@
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
   Handle speculation_log_handle = JNIHandles::resolve(speculation_log);
 
+  TraceTime install_time("installCode", GraalCompiler::codeInstallTimer());
   CodeInstaller installer;
   GraalEnv::CodeInstallResult result = installer.install(compiled_code_handle, cb, installed_code_handle, speculation_log_handle);
 
--- a/src/share/vm/graal/graalJavaAccess.cpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Thu Oct 09 00:23:17 2014 +0200
@@ -29,13 +29,16 @@
 // It looks up the name and signature symbols without creating new ones, all the symbols of these classes need to be already loaded.
 
 void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field) {
+  InstanceKlass* ik = InstanceKlass::cast(klass);
   Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
   Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
   if (name_symbol == NULL || signature_symbol == NULL) {
+#ifndef PRODUCT
+    ik->print_on(tty);
+#endif
     guarantee(false, err_msg("symbol with name %s and signature %s was not found in symbol table (klass=%s)", name, signature, klass->name()->as_C_string()));
   }
 
-  InstanceKlass* ik = InstanceKlass::cast(klass);
   fieldDescriptor fd;
   if (!ik->find_field(name_symbol, signature_symbol, &fd)) {
     ResourceMark rm;
--- a/src/share/vm/utilities/growableArray.hpp	Thu Oct 09 00:20:30 2014 +0200
+++ b/src/share/vm/utilities/growableArray.hpp	Thu Oct 09 00:23:17 2014 +0200
@@ -360,6 +360,56 @@
   void sort(int f(E*,E*), int stride) {
     qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
   }
+
+  // Binary search and insertion utility.  Search array for element
+  // matching key according to the static compare function.  Insert
+  // that element is not already in the list.  Assumes the list is
+  // already sorted according to compare function.
+  template <int compare(E, E)> E find_insert_binary(E key) {
+    bool found;
+    int location = find_binary<E, compare>(key, found);
+    if (!found) {
+      assert(location <= length(), "out of range");
+      insert_binary(location, key);
+    }
+    return at(location);
+  }
+
+  template <typename K, int compare(K, E)> int find_binary(K key, bool& found) {
+    found = false;
+    int min = 0;
+    int max = length() - 1;
+  
+    while (max >= min) {
+      int mid = (max + min) / 2;
+      E value = at(mid);
+      int diff = compare(key, value);
+      if (diff > 0) {
+        min = mid + 1;
+      } else if (diff < 0) {
+        max = mid - 1;
+      } else {
+        found = true;
+        return mid;
+      }
+    }
+    return min;
+  }
+
+  // Insert a new element at location, moving values as needed.
+  void insert_binary(int location, E element) {
+    int len = length();
+    if (len == location) {
+      append(element);
+    } else {
+      append(at(len-1));
+      int pos;
+      for (pos = len-2; pos >= location; pos--) {
+        at_put(pos+1, at(pos));
+      }
+      at_put(location, element);
+    }
+  }
 };
 
 // Global GrowableArray methods (one instance in the library per each 'E' type).