6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94

Tue, 25 Nov 2014 17:33:59 +0100

author
roland
date
Tue, 25 Nov 2014 17:33:59 +0100
changeset 7419
d3f3f7677537
parent 7418
8c08b28b7eee
child 7420
793204f5528a

6898462: The escape analysis with G1 cause crash assertion src/share/vm/runtime/vframeArray.cpp:94
Summary: OOM during reallocation of scalar replaced objects in deoptimization causes crashes
Reviewed-by: kvn, jrose

src/share/vm/interpreter/interpreterRuntime.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/universe.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/universe.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/macro.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/deoptimization.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/deoptimization.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vframeArray.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vframeArray.hpp file | annotate | diff | comparison | revisions
test/compiler/uncommontrap/TestDeoptOOM.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Dec 11 10:38:17 2014 +0000
     1.2 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Nov 25 17:33:59 2014 +0100
     1.3 @@ -398,6 +398,18 @@
     1.4    int                handler_bci;
     1.5    int                current_bci = bci(thread);
     1.6  
     1.7 +  if (thread->frames_to_pop_failed_realloc() > 0) {
     1.8 +    // Allocation of scalar replaced object used in this frame
     1.9 +    // failed. Unconditionally pop the frame.
    1.10 +    thread->dec_frames_to_pop_failed_realloc();
    1.11 +    thread->set_vm_result(h_exception());
    1.12 +    // If the method is synchronized we already unlocked the monitor
    1.13 +    // during deoptimization so the interpreter needs to skip it when
    1.14 +    // the frame is popped.
    1.15 +    thread->set_do_not_unlock_if_synchronized(true);
    1.16 +    return Interpreter::remove_activation_entry();
    1.17 +  }
    1.18 +
    1.19    // Need to do this check first since when _do_not_unlock_if_synchronized
    1.20    // is set, we don't want to trigger any classloading which may make calls
    1.21    // into java, or surprisingly find a matching exception handler for bci 0
     2.1 --- a/src/share/vm/memory/universe.cpp	Thu Dec 11 10:38:17 2014 +0000
     2.2 +++ b/src/share/vm/memory/universe.cpp	Tue Nov 25 17:33:59 2014 +0100
     2.3 @@ -119,6 +119,7 @@
     2.4  oop Universe::_out_of_memory_error_class_metaspace    = NULL;
     2.5  oop Universe::_out_of_memory_error_array_size         = NULL;
     2.6  oop Universe::_out_of_memory_error_gc_overhead_limit  = NULL;
     2.7 +oop Universe::_out_of_memory_error_realloc_objects    = NULL;
     2.8  objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
     2.9  volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
    2.10  bool Universe::_verify_in_progress                    = false;
    2.11 @@ -190,6 +191,7 @@
    2.12    f->do_oop((oop*)&_out_of_memory_error_class_metaspace);
    2.13    f->do_oop((oop*)&_out_of_memory_error_array_size);
    2.14    f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit);
    2.15 +  f->do_oop((oop*)&_out_of_memory_error_realloc_objects);
    2.16      f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
    2.17    f->do_oop((oop*)&_null_ptr_exception_instance);
    2.18    f->do_oop((oop*)&_arithmetic_exception_instance);
    2.19 @@ -574,7 +576,8 @@
    2.20            (throwable() != Universe::_out_of_memory_error_metaspace)  &&
    2.21            (throwable() != Universe::_out_of_memory_error_class_metaspace)  &&
    2.22            (throwable() != Universe::_out_of_memory_error_array_size) &&
    2.23 -          (throwable() != Universe::_out_of_memory_error_gc_overhead_limit));
    2.24 +          (throwable() != Universe::_out_of_memory_error_gc_overhead_limit) &&
    2.25 +          (throwable() != Universe::_out_of_memory_error_realloc_objects));
    2.26  }
    2.27  
    2.28  
    2.29 @@ -1044,6 +1047,7 @@
    2.30      Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
    2.31      Universe::_out_of_memory_error_gc_overhead_limit =
    2.32        k_h->allocate_instance(CHECK_false);
    2.33 +    Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
    2.34  
    2.35      // Setup preallocated NullPointerException
    2.36      // (this is currently used for a cheap & dirty solution in compiler exception handling)
    2.37 @@ -1083,6 +1087,9 @@
    2.38      msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false);
    2.39      java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg());
    2.40  
    2.41 +    msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false);
    2.42 +    java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg());
    2.43 +
    2.44      msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
    2.45      java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());
    2.46  
     3.1 --- a/src/share/vm/memory/universe.hpp	Thu Dec 11 10:38:17 2014 +0000
     3.2 +++ b/src/share/vm/memory/universe.hpp	Tue Nov 25 17:33:59 2014 +0100
     3.3 @@ -157,6 +157,7 @@
     3.4    static oop          _out_of_memory_error_class_metaspace;
     3.5    static oop          _out_of_memory_error_array_size;
     3.6    static oop          _out_of_memory_error_gc_overhead_limit;
     3.7 +  static oop          _out_of_memory_error_realloc_objects;
     3.8  
     3.9    static Array<int>*       _the_empty_int_array;    // Canonicalized int array
    3.10    static Array<u2>*        _the_empty_short_array;  // Canonicalized short array
    3.11 @@ -328,6 +329,7 @@
    3.12    static oop out_of_memory_error_class_metaspace()    { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace);   }
    3.13    static oop out_of_memory_error_array_size()         { return gen_out_of_memory_error(_out_of_memory_error_array_size); }
    3.14    static oop out_of_memory_error_gc_overhead_limit()  { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit);  }
    3.15 +  static oop out_of_memory_error_realloc_objects()    { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects);  }
    3.16  
    3.17    // Accessors needed for fast allocation
    3.18    static Klass** boolArrayKlassObj_addr()           { return &_boolArrayKlassObj;   }
     4.1 --- a/src/share/vm/opto/macro.cpp	Thu Dec 11 10:38:17 2014 +0000
     4.2 +++ b/src/share/vm/opto/macro.cpp	Tue Nov 25 17:33:59 2014 +0100
     4.3 @@ -964,7 +964,11 @@
     4.4  }
     4.5  
     4.6  bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
     4.7 -  if (!EliminateAllocations || !alloc->_is_non_escaping) {
     4.8 +  // Don't do scalar replacement if the frame can be popped by JVMTI:
     4.9 +  // if reallocation fails during deoptimization we'll pop all
    4.10 +  // interpreter frames for this compiled frame and that won't play
    4.11 +  // nice with JVMTI popframe.
    4.12 +  if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) {
    4.13      return false;
    4.14    }
    4.15    Node* klass = alloc->in(AllocateNode::KlassNode);
     5.1 --- a/src/share/vm/runtime/deoptimization.cpp	Thu Dec 11 10:38:17 2014 +0000
     5.2 +++ b/src/share/vm/runtime/deoptimization.cpp	Tue Nov 25 17:33:59 2014 +0100
     5.3 @@ -213,6 +213,8 @@
     5.4    assert(vf->is_compiled_frame(), "Wrong frame type");
     5.5    chunk->push(compiledVFrame::cast(vf));
     5.6  
     5.7 +  bool realloc_failures = false;
     5.8 +
     5.9  #ifdef COMPILER2
    5.10    // Reallocate the non-escaping objects and restore their fields. Then
    5.11    // relock objects if synchronization on them was eliminated.
    5.12 @@ -243,22 +245,19 @@
    5.13            tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, (void *)result, thread);
    5.14          }
    5.15        }
    5.16 -      bool reallocated = false;
    5.17        if (objects != NULL) {
    5.18          JRT_BLOCK
    5.19 -          reallocated = realloc_objects(thread, &deoptee, objects, THREAD);
    5.20 +          realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
    5.21          JRT_END
    5.22 +        reassign_fields(&deoptee, &map, objects, realloc_failures);
    5.23        }
    5.24 -      if (reallocated) {
    5.25 -        reassign_fields(&deoptee, &map, objects);
    5.26  #ifndef PRODUCT
    5.27 -        if (TraceDeoptimization) {
    5.28 -          ttyLocker ttyl;
    5.29 -          tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
    5.30 -          print_objects(objects);
    5.31 -        }
    5.32 +      if (TraceDeoptimization) {
    5.33 +        ttyLocker ttyl;
    5.34 +        tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
    5.35 +        print_objects(objects, realloc_failures);
    5.36 +      }
    5.37  #endif
    5.38 -      }
    5.39        if (save_oop_result) {
    5.40          // Restore result.
    5.41          deoptee.set_saved_oop_result(&map, return_value());
    5.42 @@ -273,7 +272,7 @@
    5.43          assert (cvf->scope() != NULL,"expect only compiled java frames");
    5.44          GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
    5.45          if (monitors->is_nonempty()) {
    5.46 -          relock_objects(monitors, thread);
    5.47 +          relock_objects(monitors, thread, realloc_failures);
    5.48  #ifndef PRODUCT
    5.49            if (TraceDeoptimization) {
    5.50              ttyLocker ttyl;
    5.51 @@ -284,7 +283,12 @@
    5.52                    first = false;
    5.53                    tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
    5.54                  }
    5.55 -                tty->print_cr("     object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
    5.56 +                if (mi->owner_is_scalar_replaced()) {
    5.57 +                  Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
    5.58 +                  tty->print_cr("     failed reallocation for klass %s", k->external_name());
    5.59 +                } else {
    5.60 +                  tty->print_cr("     object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
    5.61 +                }
    5.62                }
    5.63              }
    5.64            }
    5.65 @@ -299,9 +303,14 @@
    5.66    // out the java state residing in the vframeArray will be missed.
    5.67    No_Safepoint_Verifier no_safepoint;
    5.68  
    5.69 -  vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk);
    5.70 +  vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
    5.71 +#ifdef COMPILER2
    5.72 +  if (realloc_failures) {
    5.73 +    pop_frames_failed_reallocs(thread, array);
    5.74 +  }
    5.75 +#endif
    5.76  
    5.77 -  assert(thread->vframe_array_head() == NULL, "Pending deopt!");;
    5.78 +  assert(thread->vframe_array_head() == NULL, "Pending deopt!");
    5.79    thread->set_vframe_array_head(array);
    5.80  
    5.81    // Now that the vframeArray has been created if we have any deferred local writes
    5.82 @@ -753,6 +762,8 @@
    5.83    int exception_line = thread->exception_line();
    5.84    thread->clear_pending_exception();
    5.85  
    5.86 +  bool failures = false;
    5.87 +
    5.88    for (int i = 0; i < objects->length(); i++) {
    5.89      assert(objects->at(i)->is_object(), "invalid debug information");
    5.90      ObjectValue* sv = (ObjectValue*) objects->at(i);
    5.91 @@ -762,27 +773,34 @@
    5.92  
    5.93      if (k->oop_is_instance()) {
    5.94        InstanceKlass* ik = InstanceKlass::cast(k());
    5.95 -      obj = ik->allocate_instance(CHECK_(false));
    5.96 +      obj = ik->allocate_instance(THREAD);
    5.97      } else if (k->oop_is_typeArray()) {
    5.98        TypeArrayKlass* ak = TypeArrayKlass::cast(k());
    5.99        assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
   5.100        int len = sv->field_size() / type2size[ak->element_type()];
   5.101 -      obj = ak->allocate(len, CHECK_(false));
   5.102 +      obj = ak->allocate(len, THREAD);
   5.103      } else if (k->oop_is_objArray()) {
   5.104        ObjArrayKlass* ak = ObjArrayKlass::cast(k());
   5.105 -      obj = ak->allocate(sv->field_size(), CHECK_(false));
   5.106 +      obj = ak->allocate(sv->field_size(), THREAD);
   5.107      }
   5.108  
   5.109 -    assert(obj != NULL, "allocation failed");
   5.110 +    if (obj == NULL) {
   5.111 +      failures = true;
   5.112 +    }
   5.113 +
   5.114      assert(sv->value().is_null(), "redundant reallocation");
   5.115 +    assert(obj != NULL || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception");
   5.116 +    CLEAR_PENDING_EXCEPTION;
   5.117      sv->set_value(obj);
   5.118    }
   5.119  
   5.120 -  if (pending_exception.not_null()) {
   5.121 +  if (failures) {
   5.122 +    THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), failures);
   5.123 +  } else if (pending_exception.not_null()) {
   5.124      thread->set_pending_exception(pending_exception(), exception_file, exception_line);
   5.125    }
   5.126  
   5.127 -  return true;
   5.128 +  return failures;
   5.129  }
   5.130  
   5.131  // This assumes that the fields are stored in ObjectValue in the same order
   5.132 @@ -920,12 +938,15 @@
   5.133  
   5.134  
   5.135  // restore fields of all eliminated objects and arrays
   5.136 -void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects) {
   5.137 +void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
   5.138    for (int i = 0; i < objects->length(); i++) {
   5.139      ObjectValue* sv = (ObjectValue*) objects->at(i);
   5.140      KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
   5.141      Handle obj = sv->value();
   5.142 -    assert(obj.not_null(), "reallocation was missed");
   5.143 +    assert(obj.not_null() || realloc_failures, "reallocation was missed");
   5.144 +    if (obj.is_null()) {
   5.145 +      continue;
   5.146 +    }
   5.147  
   5.148      if (k->oop_is_instance()) {
   5.149        InstanceKlass* ik = InstanceKlass::cast(k());
   5.150 @@ -942,34 +963,36 @@
   5.151  
   5.152  
   5.153  // relock objects for which synchronization was eliminated
   5.154 -void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread) {
   5.155 +void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures) {
   5.156    for (int i = 0; i < monitors->length(); i++) {
   5.157      MonitorInfo* mon_info = monitors->at(i);
   5.158      if (mon_info->eliminated()) {
   5.159 -      assert(mon_info->owner() != NULL, "reallocation was missed");
   5.160 -      Handle obj = Handle(mon_info->owner());
   5.161 -      markOop mark = obj->mark();
   5.162 -      if (UseBiasedLocking && mark->has_bias_pattern()) {
   5.163 -        // New allocated objects may have the mark set to anonymously biased.
   5.164 -        // Also the deoptimized method may called methods with synchronization
   5.165 -        // where the thread-local object is bias locked to the current thread.
   5.166 -        assert(mark->is_biased_anonymously() ||
   5.167 -               mark->biased_locker() == thread, "should be locked to current thread");
   5.168 -        // Reset mark word to unbiased prototype.
   5.169 -        markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
   5.170 -        obj->set_mark(unbiased_prototype);
   5.171 +      assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed");
   5.172 +      if (!mon_info->owner_is_scalar_replaced()) {
   5.173 +        Handle obj = Handle(mon_info->owner());
   5.174 +        markOop mark = obj->mark();
   5.175 +        if (UseBiasedLocking && mark->has_bias_pattern()) {
   5.176 +          // New allocated objects may have the mark set to anonymously biased.
   5.177 +          // Also the deoptimized method may called methods with synchronization
   5.178 +          // where the thread-local object is bias locked to the current thread.
   5.179 +          assert(mark->is_biased_anonymously() ||
   5.180 +                 mark->biased_locker() == thread, "should be locked to current thread");
   5.181 +          // Reset mark word to unbiased prototype.
   5.182 +          markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
   5.183 +          obj->set_mark(unbiased_prototype);
   5.184 +        }
   5.185 +        BasicLock* lock = mon_info->lock();
   5.186 +        ObjectSynchronizer::slow_enter(obj, lock, thread);
   5.187 +        assert(mon_info->owner()->is_locked(), "object must be locked now");
   5.188        }
   5.189 -      BasicLock* lock = mon_info->lock();
   5.190 -      ObjectSynchronizer::slow_enter(obj, lock, thread);
   5.191      }
   5.192 -    assert(mon_info->owner()->is_locked(), "object must be locked now");
   5.193    }
   5.194  }
   5.195  
   5.196  
   5.197  #ifndef PRODUCT
   5.198  // print information about reallocated objects
   5.199 -void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects) {
   5.200 +void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
   5.201    fieldDescriptor fd;
   5.202  
   5.203    for (int i = 0; i < objects->length(); i++) {
   5.204 @@ -979,10 +1002,15 @@
   5.205  
   5.206      tty->print("     object <" INTPTR_FORMAT "> of type ", (void *)sv->value()());
   5.207      k->print_value();
   5.208 -    tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
   5.209 +    assert(obj.not_null() || realloc_failures, "reallocation was missed");
   5.210 +    if (obj.is_null()) {
   5.211 +      tty->print(" allocation failed");
   5.212 +    } else {
   5.213 +      tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
   5.214 +    }
   5.215      tty->cr();
   5.216  
   5.217 -    if (Verbose) {
   5.218 +    if (Verbose && !obj.is_null()) {
   5.219        k->oop_print_on(obj(), tty);
   5.220      }
   5.221    }
   5.222 @@ -990,7 +1018,7 @@
   5.223  #endif
   5.224  #endif // COMPILER2
   5.225  
   5.226 -vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) {
   5.227 +vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
   5.228    Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp());
   5.229  
   5.230  #ifndef PRODUCT
   5.231 @@ -1033,7 +1061,7 @@
   5.232    // Since the Java thread being deoptimized will eventually adjust it's own stack,
   5.233    // the vframeArray containing the unpacking information is allocated in the C heap.
   5.234    // For Compiler1, the caller of the deoptimized frame is saved for use by unpack_frames().
   5.235 -  vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr);
   5.236 +  vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr, realloc_failures);
   5.237  
   5.238    // Compare the vframeArray to the collected vframes
   5.239    assert(array->structural_compare(thread, chunk), "just checking");
   5.240 @@ -1048,6 +1076,33 @@
   5.241    return array;
   5.242  }
   5.243  
   5.244 +#ifdef COMPILER2
   5.245 +void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
   5.246 +  // Reallocation of some scalar replaced objects failed. Record
   5.247 +  // that we need to pop all the interpreter frames for the
   5.248 +  // deoptimized compiled frame.
   5.249 +  assert(thread->frames_to_pop_failed_realloc() == 0, "missed frames to pop?");
   5.250 +  thread->set_frames_to_pop_failed_realloc(array->frames());
   5.251 +  // Unlock all monitors here otherwise the interpreter will see a
   5.252 +  // mix of locked and unlocked monitors (because of failed
   5.253 +  // reallocations of synchronized objects) and be confused.
   5.254 +  for (int i = 0; i < array->frames(); i++) {
   5.255 +    MonitorChunk* monitors = array->element(i)->monitors();
   5.256 +    if (monitors != NULL) {
   5.257 +      for (int j = 0; j < monitors->number_of_monitors(); j++) {
   5.258 +        BasicObjectLock* src = monitors->at(j);
   5.259 +        if (src->obj() != NULL) {
   5.260 +          ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
   5.261 +        }
   5.262 +      }
   5.263 +      array->element(i)->free_monitors(thread);
   5.264 +#ifdef ASSERT
   5.265 +      array->element(i)->set_removed_monitors();
   5.266 +#endif
   5.267 +    }
   5.268 +  }
   5.269 +}
   5.270 +#endif
   5.271  
   5.272  static void collect_monitors(compiledVFrame* cvf, GrowableArray<Handle>* objects_to_revoke) {
   5.273    GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
     6.1 --- a/src/share/vm/runtime/deoptimization.hpp	Thu Dec 11 10:38:17 2014 +0000
     6.2 +++ b/src/share/vm/runtime/deoptimization.hpp	Tue Nov 25 17:33:59 2014 +0100
     6.3 @@ -120,13 +120,14 @@
     6.4    static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
     6.5    static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
     6.6    static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
     6.7 -  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
     6.8 -  static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
     6.9 -  NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
    6.10 +  static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures);
    6.11 +  static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
    6.12 +  static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
    6.13 +  NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
    6.14  #endif // COMPILER2
    6.15  
    6.16    public:
    6.17 -  static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);
    6.18 +  static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
    6.19  
    6.20    // Interface used for unpacking deoptimized frames
    6.21  
     7.1 --- a/src/share/vm/runtime/sharedRuntime.cpp	Thu Dec 11 10:38:17 2014 +0000
     7.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp	Tue Nov 25 17:33:59 2014 +0100
     7.3 @@ -482,6 +482,7 @@
     7.4  
     7.5  address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {
     7.6    assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address));
     7.7 +  assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?");
     7.8  
     7.9    // Reset method handle flag.
    7.10    thread->set_is_method_handle_return(false);
     8.1 --- a/src/share/vm/runtime/thread.cpp	Thu Dec 11 10:38:17 2014 +0000
     8.2 +++ b/src/share/vm/runtime/thread.cpp	Tue Nov 25 17:33:59 2014 +0100
     8.3 @@ -1495,6 +1495,7 @@
     8.4    _popframe_condition = popframe_inactive;
     8.5    _popframe_preserved_args = NULL;
     8.6    _popframe_preserved_args_size = 0;
     8.7 +  _frames_to_pop_failed_realloc = 0;
     8.8  
     8.9    pd_initialize();
    8.10  }
     9.1 --- a/src/share/vm/runtime/thread.hpp	Thu Dec 11 10:38:17 2014 +0000
     9.2 +++ b/src/share/vm/runtime/thread.hpp	Tue Nov 25 17:33:59 2014 +0100
     9.3 @@ -933,6 +933,12 @@
     9.4    // This is set to popframe_pending to signal that top Java frame should be popped immediately
     9.5    int _popframe_condition;
     9.6  
     9.7 +  // If reallocation of scalar replaced objects fails, we throw OOM
     9.8 +  // and during exception propagation, pop the top
     9.9 +  // _frames_to_pop_failed_realloc frames, the ones that reference
    9.10 +  // failed reallocations.
    9.11 +  int _frames_to_pop_failed_realloc;
    9.12 +
    9.13  #ifndef PRODUCT
    9.14    int _jmp_ring_index;
    9.15    struct {
    9.16 @@ -1585,6 +1591,10 @@
    9.17    void clr_pop_frame_in_process(void)                 { _popframe_condition &= ~popframe_processing_bit; }
    9.18  #endif
    9.19  
    9.20 +  int frames_to_pop_failed_realloc() const            { return _frames_to_pop_failed_realloc; }
    9.21 +  void set_frames_to_pop_failed_realloc(int nb)       { _frames_to_pop_failed_realloc = nb; }
    9.22 +  void dec_frames_to_pop_failed_realloc()             { _frames_to_pop_failed_realloc--; }
    9.23 +
    9.24   private:
    9.25    // Saved incoming arguments to popped frame.
    9.26    // Used only when popped interpreted frame returns to deoptimized frame.
    10.1 --- a/src/share/vm/runtime/vframeArray.cpp	Thu Dec 11 10:38:17 2014 +0000
    10.2 +++ b/src/share/vm/runtime/vframeArray.cpp	Tue Nov 25 17:33:59 2014 +0100
    10.3 @@ -56,7 +56,7 @@
    10.4    }
    10.5  }
    10.6  
    10.7 -void vframeArrayElement::fill_in(compiledVFrame* vf) {
    10.8 +void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
    10.9  
   10.10  // Copy the information from the compiled vframe to the
   10.11  // interpreter frame we will be creating to replace vf
   10.12 @@ -64,6 +64,9 @@
   10.13    _method = vf->method();
   10.14    _bci    = vf->raw_bci();
   10.15    _reexecute = vf->should_reexecute();
   10.16 +#ifdef ASSERT
   10.17 +  _removed_monitors = false;
   10.18 +#endif
   10.19  
   10.20    int index;
   10.21  
   10.22 @@ -81,11 +84,15 @@
   10.23      // Migrate the BasicLocks from the stack to the monitor chunk
   10.24      for (index = 0; index < list->length(); index++) {
   10.25        MonitorInfo* monitor = list->at(index);
   10.26 -      assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already");
   10.27 -      assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
   10.28 +      assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
   10.29        BasicObjectLock* dest = _monitors->at(index);
   10.30 -      dest->set_obj(monitor->owner());
   10.31 -      monitor->lock()->move_to(monitor->owner(), dest->lock());
   10.32 +      if (monitor->owner_is_scalar_replaced()) {
   10.33 +        dest->set_obj(NULL);
   10.34 +      } else {
   10.35 +        assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
   10.36 +        dest->set_obj(monitor->owner());
   10.37 +        monitor->lock()->move_to(monitor->owner(), dest->lock());
   10.38 +      }
   10.39      }
   10.40    }
   10.41  
   10.42 @@ -110,7 +117,7 @@
   10.43      StackValue* value = locs->at(index);
   10.44      switch(value->type()) {
   10.45        case T_OBJECT:
   10.46 -        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
   10.47 +        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
   10.48          // preserve object type
   10.49          _locals->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
   10.50          break;
   10.51 @@ -135,7 +142,7 @@
   10.52      StackValue* value = exprs->at(index);
   10.53      switch(value->type()) {
   10.54        case T_OBJECT:
   10.55 -        assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
   10.56 +        assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
   10.57          // preserve object type
   10.58          _expressions->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
   10.59          break;
   10.60 @@ -286,7 +293,7 @@
   10.61  
   10.62    _frame.patch_pc(thread, pc);
   10.63  
   10.64 -  assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
   10.65 +  assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
   10.66  
   10.67    BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
   10.68    for (int index = 0; index < locks; index++) {
   10.69 @@ -438,7 +445,8 @@
   10.70  
   10.71  
   10.72  vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
   10.73 -                                   RegisterMap *reg_map, frame sender, frame caller, frame self) {
   10.74 +                                   RegisterMap *reg_map, frame sender, frame caller, frame self,
   10.75 +                                   bool realloc_failures) {
   10.76  
   10.77    // Allocate the vframeArray
   10.78    vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
   10.79 @@ -450,19 +458,20 @@
   10.80    result->_caller = caller;
   10.81    result->_original = self;
   10.82    result->set_unroll_block(NULL); // initialize it
   10.83 -  result->fill_in(thread, frame_size, chunk, reg_map);
   10.84 +  result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures);
   10.85    return result;
   10.86  }
   10.87  
   10.88  void vframeArray::fill_in(JavaThread* thread,
   10.89                            int frame_size,
   10.90                            GrowableArray<compiledVFrame*>* chunk,
   10.91 -                          const RegisterMap *reg_map) {
   10.92 +                          const RegisterMap *reg_map,
   10.93 +                          bool realloc_failures) {
   10.94    // Set owner first, it is used when adding monitor chunks
   10.95  
   10.96    _frame_size = frame_size;
   10.97    for(int i = 0; i < chunk->length(); i++) {
   10.98 -    element(i)->fill_in(chunk->at(i));
   10.99 +    element(i)->fill_in(chunk->at(i), realloc_failures);
  10.100    }
  10.101  
  10.102    // Copy registers for callee-saved registers
    11.1 --- a/src/share/vm/runtime/vframeArray.hpp	Thu Dec 11 10:38:17 2014 +0000
    11.2 +++ b/src/share/vm/runtime/vframeArray.hpp	Tue Nov 25 17:33:59 2014 +0100
    11.3 @@ -58,6 +58,9 @@
    11.4      MonitorChunk* _monitors;                                     // active monitors for this vframe
    11.5      StackValueCollection* _locals;
    11.6      StackValueCollection* _expressions;
    11.7 +#ifdef ASSERT
    11.8 +    bool _removed_monitors;
    11.9 +#endif
   11.10  
   11.11    public:
   11.12  
   11.13 @@ -78,7 +81,7 @@
   11.14  
   11.15    StackValueCollection* expressions(void) const        { return _expressions; }
   11.16  
   11.17 -  void fill_in(compiledVFrame* vf);
   11.18 +  void fill_in(compiledVFrame* vf, bool realloc_failures);
   11.19  
   11.20    // Formerly part of deoptimizedVFrame
   11.21  
   11.22 @@ -99,6 +102,12 @@
   11.23                         bool is_bottom_frame,
   11.24                         int exec_mode);
   11.25  
   11.26 +#ifdef ASSERT
   11.27 +  void set_removed_monitors() {
   11.28 +    _removed_monitors = true;
   11.29 +  }
   11.30 +#endif
   11.31 +
   11.32  #ifndef PRODUCT
   11.33    void print(outputStream* st);
   11.34  #endif /* PRODUCT */
   11.35 @@ -160,13 +169,14 @@
   11.36    int frames() const                            { return _frames;   }
   11.37  
   11.38    static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
   11.39 -                               RegisterMap* reg_map, frame sender, frame caller, frame self);
   11.40 +                               RegisterMap* reg_map, frame sender, frame caller, frame self,
   11.41 +                               bool realloc_failures);
   11.42  
   11.43  
   11.44    vframeArrayElement* element(int index)        { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; }
   11.45  
   11.46    // Allocates a new vframe in the array and fills the array with vframe information in chunk
   11.47 -  void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map);
   11.48 +  void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map, bool realloc_failures);
   11.49  
   11.50    // Returns the owner of this vframeArray
   11.51    JavaThread* owner_thread() const           { return _owner_thread; }
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/compiler/uncommontrap/TestDeoptOOM.java	Tue Nov 25 17:33:59 2014 +0100
    12.3 @@ -0,0 +1,426 @@
    12.4 +/*
    12.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.
   12.11 + *
   12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.15 + * version 2 for more details (a copy is included in the LICENSE file that
   12.16 + * accompanied this code).
   12.17 + *
   12.18 + * You should have received a copy of the GNU General Public License version
   12.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.21 + *
   12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.23 + * or visit www.oracle.com if you need additional information or have any
   12.24 + * questions.
   12.25 + */
   12.26 +
   12.27 +/*
   12.28 + * @test
   12.29 + * @bug 6898462
   12.30 + * @summary failed reallocations of scalar replaced objects during deoptimization causes crash
   12.31 + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=exclude,TestDeoptOOM::main -XX:CompileCommand=exclude,TestDeoptOOM::m9_1 -Xmx128M TestDeoptOOM
   12.32 + *
   12.33 + */
   12.34 +
   12.35 +public class TestDeoptOOM {
   12.36 +
   12.37 +    long f1;
   12.38 +    long f2;
   12.39 +    long f3;
   12.40 +    long f4;
   12.41 +    long f5;
   12.42 +
   12.43 +    static class LinkedList {
   12.44 +        LinkedList l;
   12.45 +        long[] array;
   12.46 +        LinkedList(LinkedList l, int size) {
   12.47 +            array = new long[size];
   12.48 +            this.l = l;
   12.49 +        }
   12.50 +    }
   12.51 +
   12.52 +    static LinkedList ll;
   12.53 +
   12.54 +    static void consume_all_memory() {
   12.55 +        int size = 128 * 1024 * 1024;
   12.56 +        while(size > 0) {
   12.57 +            try {
   12.58 +                while(true) {
   12.59 +                    ll = new LinkedList(ll, size);
   12.60 +                }
   12.61 +            } catch(OutOfMemoryError oom) {
   12.62 +            }
   12.63 +            size = size / 2;
   12.64 +        }
   12.65 +    }
   12.66 +
   12.67 +    static void free_memory() {
   12.68 +        ll = null;
   12.69 +    }
   12.70 +
   12.71 +    static TestDeoptOOM m1(boolean deopt) {
   12.72 +        try {
   12.73 +            TestDeoptOOM tdoom = new TestDeoptOOM();
   12.74 +            if (deopt) {
   12.75 +                return tdoom;
   12.76 +            }
   12.77 +        } catch(OutOfMemoryError oom) {
   12.78 +            free_memory();
   12.79 +            System.out.println("OOM caught in m1");
   12.80 +        }
   12.81 +        return null;
   12.82 +    }
   12.83 +
   12.84 +    static TestDeoptOOM m2_1(boolean deopt) {
   12.85 +        try {
   12.86 +            TestDeoptOOM tdoom = new TestDeoptOOM();
   12.87 +            if (deopt) {
   12.88 +                return tdoom;
   12.89 +            }
   12.90 +        } catch(OutOfMemoryError oom) {
   12.91 +            free_memory();
   12.92 +            System.out.println("OOM caught in m2_1");
   12.93 +        }
   12.94 +        return null;
   12.95 +    }
   12.96 +
   12.97 +    static TestDeoptOOM m2(boolean deopt) {
   12.98 +        try {
   12.99 +            return m2_1(deopt);
  12.100 +        } catch(OutOfMemoryError oom) {
  12.101 +            free_memory();
  12.102 +            System.out.println("OOM caught in m2");
  12.103 +        }
  12.104 +        return null;
  12.105 +    }
  12.106 +
  12.107 +    static TestDeoptOOM m3_3(boolean deopt) {
  12.108 +        try {
  12.109 +            TestDeoptOOM tdoom = new TestDeoptOOM();
  12.110 +            if (deopt) {
  12.111 +                return tdoom;
  12.112 +            }
  12.113 +        } catch(OutOfMemoryError oom) {
  12.114 +            free_memory();
  12.115 +            System.out.println("OOM caught in m3_3");
  12.116 +        }
  12.117 +        return null;
  12.118 +    }
  12.119 +
  12.120 +    static boolean m3_2(boolean deopt) {
  12.121 +        try {
  12.122 +            return m3_3(deopt) != null;
  12.123 +        } catch(OutOfMemoryError oom) {
  12.124 +            free_memory();
  12.125 +            System.out.println("OOM caught in m3_2");
  12.126 +        }
  12.127 +        return false;
  12.128 +    }
  12.129 +
  12.130 +    static TestDeoptOOM m3_1(boolean deopt) {
  12.131 +        try {
  12.132 +            TestDeoptOOM tdoom = new TestDeoptOOM();
  12.133 +            if (m3_2(deopt)) {
  12.134 +                return tdoom;
  12.135 +            }
  12.136 +        } catch(OutOfMemoryError oom) {
  12.137 +            free_memory();
  12.138 +            System.out.println("OOM caught in m3_1");
  12.139 +        }
  12.140 +        return null;
  12.141 +    }
  12.142 +
  12.143 +    static TestDeoptOOM m3(boolean deopt) {
  12.144 +        try {
  12.145 +            return m3_1(deopt);
  12.146 +        } catch(OutOfMemoryError oom) {
  12.147 +            free_memory();
  12.148 +            System.out.println("OOM caught in m3");
  12.149 +        }
  12.150 +        return null;
  12.151 +    }
  12.152 +
  12.153 +    static TestDeoptOOM m4(boolean deopt) {
  12.154 +        try {
  12.155 +            TestDeoptOOM tdoom = new TestDeoptOOM();
  12.156 +            if (deopt) {
  12.157 +                tdoom.f1 = 1l;
  12.158 +                tdoom.f2 = 2l;
  12.159 +                tdoom.f3 = 3l;
  12.160 +                return tdoom;
  12.161 +            }
  12.162 +        } catch(OutOfMemoryError oom) {
  12.163 +            free_memory();
  12.164 +            System.out.println("OOM caught in m4");
  12.165 +        }
  12.166 +        return null;
  12.167 +    }
  12.168 +
  12.169 +    static TestDeoptOOM m5(boolean deopt) {
  12.170 +        try {
  12.171 +            TestDeoptOOM tdoom = new TestDeoptOOM();
  12.172 +            synchronized(tdoom) {
  12.173 +                if (deopt) {
  12.174 +                    return tdoom;
  12.175 +                }
  12.176 +            }
  12.177 +        } catch(OutOfMemoryError oom) {
  12.178 +            free_memory();
  12.179 +            System.out.println("OOM caught in m5");
  12.180 +        }
  12.181 +        return null;
  12.182 +    }
  12.183 +
  12.184 +    synchronized TestDeoptOOM m6_1(boolean deopt) {
  12.185 +        if (deopt) {
  12.186 +            return this;
  12.187 +        }
  12.188 +        return null;
  12.189 +    }
  12.190 +
  12.191 +    static TestDeoptOOM m6(boolean deopt) {
  12.192 +        try {
  12.193 +            TestDeoptOOM tdoom = new TestDeoptOOM();
  12.194 +            return tdoom.m6_1(deopt);
  12.195 +        } catch(OutOfMemoryError oom) {
  12.196 +            free_memory();
  12.197 +            System.out.println("OOM caught in m6");
  12.198 +        }
  12.199 +        return null;
  12.200 +    }
  12.201 +
  12.202 +    static TestDeoptOOM m7_1(boolean deopt, Object lock) {
  12.203 +        try {
  12.204 +            synchronized(lock) {
  12.205 +                TestDeoptOOM tdoom = new TestDeoptOOM();
  12.206 +                if (deopt) {
  12.207 +                    return tdoom;
  12.208 +                }
  12.209 +            }
  12.210 +        } catch(OutOfMemoryError oom) {
  12.211 +            free_memory();
  12.212 +            System.out.println("OOM caught in m7_1");
  12.213 +        }
  12.214 +        return null;
  12.215 +    }
  12.216 +
  12.217 +    static TestDeoptOOM m7(boolean deopt, Object lock) {
  12.218 +        try {
  12.219 +            return m7_1(deopt, lock);
  12.220 +        } catch(OutOfMemoryError oom) {
  12.221 +            free_memory();
  12.222 +            System.out.println("OOM caught in m7");
  12.223 +        }
  12.224 +        return null;
  12.225 +    }
  12.226 +
  12.227 +    static class A {
  12.228 +        long f1;
  12.229 +        long f2;
  12.230 +        long f3;
  12.231 +        long f4;
  12.232 +        long f5;
  12.233 +    }
  12.234 +
  12.235 +    static class B {
  12.236 +        long f1;
  12.237 +        long f2;
  12.238 +        long f3;
  12.239 +        long f4;
  12.240 +        long f5;
  12.241 +
  12.242 +        A a;
  12.243 +    }
  12.244 +
  12.245 +    static B m8(boolean deopt) {
  12.246 +        try {
  12.247 +            A a = new A();
  12.248 +            B b = new B();
  12.249 +            b.a = a;
  12.250 +            if (deopt) {
  12.251 +                return b;
  12.252 +            }
  12.253 +        } catch(OutOfMemoryError oom) {
  12.254 +            free_memory();
  12.255 +            System.out.println("OOM caught in m8");
  12.256 +        }
  12.257 +        return null;
  12.258 +    }
  12.259 +
  12.260 +    static void m9_1(int i) {
  12.261 +        if (i > 90000) {
  12.262 +            consume_all_memory();
  12.263 +        }
  12.264 +    }
  12.265 +
  12.266 +    static TestDeoptOOM m9() {
  12.267 +        try {
  12.268 +            for (int i = 0; i < 100000; i++) {
  12.269 +                TestDeoptOOM tdoom = new TestDeoptOOM();
  12.270 +                m9_1(i);
  12.271 +                if (i > 90000) {
  12.272 +                    return tdoom;
  12.273 +                }
  12.274 +            }
  12.275 +        } catch(OutOfMemoryError oom) {
  12.276 +            free_memory();
  12.277 +            System.out.println("OOM caught in m1");
  12.278 +        }
  12.279 +        return null;
  12.280 +    }
  12.281 +
  12.282 +    public static void main(String[] args) {
  12.283 +        for (int i = 0; i < 20000; i++) {
  12.284 +            m1(false);
  12.285 +        }
  12.286 +
  12.287 +        consume_all_memory();
  12.288 +
  12.289 +        try {
  12.290 +            m1(true);
  12.291 +        } catch(OutOfMemoryError oom) {
  12.292 +            free_memory();
  12.293 +            System.out.println("OOM caught in main " + oom.getMessage());
  12.294 +        }
  12.295 +
  12.296 +        free_memory();
  12.297 +
  12.298 +        for (int i = 0; i < 20000; i++) {
  12.299 +            m2(false);
  12.300 +        }
  12.301 +
  12.302 +        consume_all_memory();
  12.303 +
  12.304 +        try {
  12.305 +            m2(true);
  12.306 +        } catch(OutOfMemoryError oom) {
  12.307 +            free_memory();
  12.308 +            System.out.println("OOM caught in main");
  12.309 +        }
  12.310 +
  12.311 +        free_memory();
  12.312 +
  12.313 +        for (int i = 0; i < 20000; i++) {
  12.314 +            m3(false);
  12.315 +        }
  12.316 +
  12.317 +        consume_all_memory();
  12.318 +
  12.319 +        try {
  12.320 +            m3(true);
  12.321 +        } catch(OutOfMemoryError oom) {
  12.322 +            free_memory();
  12.323 +            System.out.println("OOM caught in main");
  12.324 +        }
  12.325 +
  12.326 +        free_memory();
  12.327 +
  12.328 +        for (int i = 0; i < 20000; i++) {
  12.329 +            m4(false);
  12.330 +        }
  12.331 +
  12.332 +        consume_all_memory();
  12.333 +
  12.334 +        try {
  12.335 +            m4(true);
  12.336 +        } catch(OutOfMemoryError oom) {
  12.337 +            free_memory();
  12.338 +            System.out.println("OOM caught in main");
  12.339 +        }
  12.340 +
  12.341 +        free_memory();
  12.342 +
  12.343 +        for (int i = 0; i < 20000; i++) {
  12.344 +            m5(false);
  12.345 +        }
  12.346 +
  12.347 +        consume_all_memory();
  12.348 +
  12.349 +        try {
  12.350 +            m5(true);
  12.351 +        } catch(OutOfMemoryError oom) {
  12.352 +            free_memory();
  12.353 +            System.out.println("OOM caught in main");
  12.354 +        }
  12.355 +
  12.356 +        free_memory();
  12.357 +
  12.358 +        for (int i = 0; i < 20000; i++) {
  12.359 +            m6(false);
  12.360 +        }
  12.361 +
  12.362 +        consume_all_memory();
  12.363 +
  12.364 +        try {
  12.365 +            m6(true);
  12.366 +        } catch(OutOfMemoryError oom) {
  12.367 +            free_memory();
  12.368 +            System.out.println("OOM caught in main");
  12.369 +        }
  12.370 +
  12.371 +        free_memory();
  12.372 +
  12.373 +        final Object lock = new Object();
  12.374 +
  12.375 +        for (int i = 0; i < 20000; i++) {
  12.376 +            m7(false, lock);
  12.377 +        }
  12.378 +
  12.379 +        consume_all_memory();
  12.380 +
  12.381 +        try {
  12.382 +            m7(true, lock);
  12.383 +        } catch(OutOfMemoryError oom) {
  12.384 +            free_memory();
  12.385 +            System.out.println("OOM caught in main");
  12.386 +        }
  12.387 +
  12.388 +        free_memory();
  12.389 +
  12.390 +        Thread thread = new Thread() {
  12.391 +                public void run() {
  12.392 +                    System.out.println("Acquiring lock");
  12.393 +                    synchronized(lock) {
  12.394 +                        System.out.println("Lock acquired");
  12.395 +                    }
  12.396 +                    System.out.println("Lock released");
  12.397 +                }
  12.398 +            };
  12.399 +        thread.start();
  12.400 +        try {
  12.401 +            thread.join();
  12.402 +        } catch(InterruptedException ie) {
  12.403 +        }
  12.404 +
  12.405 +        for (int i = 0; i < 20000; i++) {
  12.406 +            m8(false);
  12.407 +        }
  12.408 +
  12.409 +        consume_all_memory();
  12.410 +
  12.411 +        try {
  12.412 +            m8(true);
  12.413 +        } catch(OutOfMemoryError oom) {
  12.414 +            free_memory();
  12.415 +            System.out.println("OOM caught in main");
  12.416 +        }
  12.417 +
  12.418 +        free_memory();
  12.419 +
  12.420 +        try {
  12.421 +            m9();
  12.422 +        } catch(OutOfMemoryError oom) {
  12.423 +            free_memory();
  12.424 +            System.out.println("OOM caught in main");
  12.425 +        }
  12.426 +
  12.427 +        free_memory();
  12.428 +    }
  12.429 +}

mercurial