8046936: JEP 270: Reserved Stack Areas for Critical Sections
authorfparain
Fri, 11 Dec 2015 09:07:07 -0800
changeset 35071 a0910b1d3e0d
parent 35066 cd4ac076bf7f
child 35072 10df35fbf0b7
8046936: JEP 270: Reserved Stack Areas for Critical Sections Reviewed-by: acorn, dcubed
hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/frame_sparc.cpp
hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp
hotspot/src/cpu/sparc/vm/globals_sparc.hpp
hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp
hotspot/src/cpu/sparc/vm/sparc.ad
hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp
hotspot/src/cpu/x86/vm/globals_x86.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
hotspot/src/cpu/x86/vm/x86_32.ad
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/cpu/zero/vm/globals_zero.hpp
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
hotspot/src/os/bsd/vm/os_bsd.cpp
hotspot/src/os/bsd/vm/os_bsd.hpp
hotspot/src/os/linux/vm/os_linux.cpp
hotspot/src/os/linux/vm/os_linux.hpp
hotspot/src/os/solaris/vm/os_solaris.cpp
hotspot/src/os/solaris/vm/os_solaris.hpp
hotspot/src/os/windows/vm/os_windows.cpp
hotspot/src/os/windows/vm/os_windows.hpp
hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
hotspot/src/share/vm/c1/c1_Compilation.cpp
hotspot/src/share/vm/c1/c1_Compilation.hpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/c1/c1_Runtime1.cpp
hotspot/src/share/vm/ci/ciMethod.cpp
hotspot/src/share/vm/ci/ciMethod.hpp
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/interpreter/interpreterRuntime.hpp
hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
hotspot/src/share/vm/memory/universe.cpp
hotspot/src/share/vm/memory/universe.hpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/compile.hpp
hotspot/src/share/vm/opto/parse1.cpp
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/src/share/vm/runtime/deoptimization.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/javaCalls.cpp
hotspot/src/share/vm/runtime/os.cpp
hotspot/src/share/vm/runtime/os.hpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.hpp
hotspot/src/share/vm/runtime/stubRoutines.cpp
hotspot/src/share/vm/runtime/stubRoutines.hpp
hotspot/src/share/vm/runtime/thread.cpp
hotspot/src/share/vm/runtime/thread.hpp
hotspot/src/share/vm/runtime/thread.inline.hpp
hotspot/src/share/vm/runtime/vmStructs.cpp
hotspot/src/share/vm/trace/trace.xml
hotspot/test/runtime/ReservedStack/ReservedStackTest.java
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -58,14 +58,17 @@
 #define DEFAULT_STACK_YELLOW_PAGES (2)
 #define DEFAULT_STACK_RED_PAGES (1)
 #define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
+#define DEFAULT_STACK_RESERVED_PAGES (0)
 
 #define MIN_STACK_YELLOW_PAGES 1
 #define MIN_STACK_RED_PAGES    1
 #define MIN_STACK_SHADOW_PAGES 1
+#define MIN_STACK_RESERVED_PAGES (0)
 
 define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
 define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
 define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
+define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1453,6 +1453,9 @@
 
 
 void LIR_Assembler::return_op(LIR_Opr result) {
+  if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
   // the poll may need a register so just pick one that isn't the return register
 #if defined(TIERED) && !defined(_LP64)
   if (result->type_field() == LIR_OprDesc::long_type) {
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -632,7 +632,7 @@
 
   // stack frames shouldn't be much larger than max_stack elements
 
-  if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) {
+  if (fp() - unextended_sp() > 1024 + m->max_stack()*Interpreter::stackElementSize) {
     return false;
   }
 
--- a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -54,4 +54,8 @@
   #endif
 #endif
 
+#if defined(SOLARIS)
+#define SUPPORT_RESERVED_STACK_AREA
+#endif
+
 #endif // CPU_SPARC_VM_GLOBALDEFINITIONS_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -54,6 +54,7 @@
 
 #define DEFAULT_STACK_YELLOW_PAGES (2)
 #define DEFAULT_STACK_RED_PAGES (1)
+#define DEFAULT_STACK_RESERVED_PAGES (SOLARIS_ONLY(1) NOT_SOLARIS(0))
 
 #ifdef _LP64
 // Stack slots are 2X larger in LP64 than in the 32 bit VM.
@@ -69,10 +70,12 @@
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
 #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
 #define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+#define MIN_STACK_RESERVED_PAGES (0)
 
 define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
 define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
 define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
+define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1140,6 +1140,19 @@
   // save result (push state before jvmti call and pop it afterwards) and notify jvmti
   notify_method_exit(false, state, NotifyJVMTI);
 
+  if (StackReservedPages > 0) {
+    // testing if Stack Reserved Area needs to be re-enabled
+    Label no_reserved_zone_enabling;
+    ld_ptr(G2_thread, JavaThread::reserved_stack_activation_offset(), G3_scratch);
+    cmp_and_brx_short(SP, G3_scratch, Assembler::lessUnsigned, Assembler::pt, no_reserved_zone_enabling);
+
+    call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), G2_thread);
+    call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError), G2_thread);
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+  }
+
   interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
   verify_thread();
 
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -3601,6 +3601,24 @@
   }
 }
 
+void MacroAssembler::reserved_stack_check() {
+  // testing if reserved zone needs to be enabled
+  Label no_reserved_zone_enabling;
+
+  ld_ptr(G2_thread, JavaThread::reserved_stack_activation_offset(), G4_scratch);
+  cmp_and_brx_short(SP, G4_scratch, Assembler::lessUnsigned, Assembler::pt, no_reserved_zone_enabling);
+
+  call_VM_leaf(L0, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), G2_thread);
+
+  AddressLiteral stub(StubRoutines::throw_delayed_StackOverflowError_entry());
+  jump_to(stub, G4_scratch);
+  delayed()->restore();
+
+  should_not_reach_here();
+
+  bind(no_reserved_zone_enabling);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 #if INCLUDE_ALL_GCS
 
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1422,6 +1422,9 @@
   // stack overflow + shadow pages.  Clobbers tsp and scratch registers.
   void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
 
+  // Check for reserved stack access in method being exited (for JIT)
+  void reserved_stack_check();
+
   virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset);
 
   void verify_tlab();
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Fri Dec 11 09:07:07 2015 -0800
@@ -1294,6 +1294,10 @@
 
   __ verify_thread();
 
+  if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
+
   // If this does safepoint polling, then do it here
   if(do_polling() && ra_->C->is_method_compilation()) {
     AddressLiteral polling_page(os::get_polling_page());
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -5355,7 +5355,12 @@
 #endif  // COMPILER2 !=> _LP64
 
     // Build this early so it's available for the interpreter.
-    StubRoutines::_throw_StackOverflowError_entry          = generate_throw_exception("StackOverflowError throw_exception",           CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
+    StubRoutines::_throw_StackOverflowError_entry =
+            generate_throw_exception("StackOverflowError throw_exception",
+            CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
+    StubRoutines::_throw_delayed_StackOverflowError_entry =
+            generate_throw_exception("delayed StackOverflowError throw_exception",
+            CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError));
 
     if (UseCRC32Intrinsics) {
       // set table address before stub generation which use it
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -518,6 +518,10 @@
   // Pop the stack before the safepoint code
   __ remove_frame(initial_frame_size_in_bytes());
 
+  if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
+
   bool result_is_oop = result->is_valid() ? result->is_oop() : false;
 
   // Note: we do not need to round double result; float result has the right precision
--- a/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -57,4 +57,8 @@
 #define INCLUDE_RTM_OPT 1
 #endif
 
+#if defined(LINUX) || defined(SOLARIS) || defined(__APPLE__)
+#define SUPPORT_RESERVED_STACK_AREA
+#endif
+
 #endif // CPU_X86_VM_GLOBALDEFINITIONS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -57,9 +57,11 @@
 
 #define DEFAULT_STACK_YELLOW_PAGES (NOT_WINDOWS(2) WINDOWS_ONLY(3))
 #define DEFAULT_STACK_RED_PAGES (1)
+#define DEFAULT_STACK_RESERVED_PAGES (NOT_WINDOWS(1) WINDOWS_ONLY(0))
 
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
 #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+#define MIN_STACK_RESERVED_PAGES (0)
 
 #ifdef AMD64
 // Very large C++ stack frames using solaris-amd64 optimized builds
@@ -76,6 +78,7 @@
 define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
 define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
 define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
+define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
 
 define_pd_global(bool, RewriteBytecodes,     true);
 define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1023,6 +1023,25 @@
   // get sender sp
   movptr(rbx,
          Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize));
+  if (StackReservedPages > 0) {
+    // testing if reserved zone needs to be re-enabled
+    Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
+    Label no_reserved_zone_enabling;
+
+    NOT_LP64(get_thread(rthread);)
+
+    cmpptr(rbx, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+    jcc(Assembler::lessEqual, no_reserved_zone_enabling);
+
+    call_VM_leaf(
+      CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
+    push(rthread);
+    call_VM(noreg, CAST_FROM_FN_PTR(address,
+                   InterpreterRuntime::throw_delayed_StackOverflowError));
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+  }
   leave();                           // remove frame anchor
   pop(ret_addr);                     // get return address
   mov(rsp, rbx);                     // set sp to sender sp
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1067,6 +1067,22 @@
   }
 }
 
+void MacroAssembler::reserved_stack_check() {
+    // testing if reserved zone needs to be enabled
+    Label no_reserved_zone_enabling;
+    Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
+    NOT_LP64(get_thread(rsi);)
+
+    cmpptr(rsp, Address(thread, JavaThread::reserved_stack_activation_offset()));
+    jcc(Assembler::below, no_reserved_zone_enabling);
+
+    call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), thread);
+    jump(RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
+    should_not_reach_here();
+
+    bind(no_reserved_zone_enabling);
+}
+
 int MacroAssembler::biased_locking_enter(Register lock_reg,
                                          Register obj_reg,
                                          Register swap_reg,
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -641,6 +641,9 @@
   // stack overflow + shadow pages.  Also, clobbers tmp
   void bang_stack_size(Register size, Register tmp);
 
+  // Check for reserved stack access in method being exited (for JIT)
+  void reserved_stack_check();
+
   virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
                                                 Register tmp,
                                                 int offset);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -3290,7 +3290,10 @@
                                                                                    CAST_FROM_FN_PTR(address, SharedRuntime::d2l));
 
     // Build this early so it's available for the interpreter
-    StubRoutines::_throw_StackOverflowError_entry          = generate_throw_exception("StackOverflowError throw_exception",           CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
+    StubRoutines::_throw_StackOverflowError_entry          = generate_throw_exception("StackOverflowError throw_exception",
+                                                                                      CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
+    StubRoutines::_throw_delayed_StackOverflowError_entry  = generate_throw_exception("delayed StackOverflowError throw_exception",
+                                                                                      CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError));
 
     if (UseCRC32Intrinsics) {
       // set table address before stub generation which use it
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -4410,6 +4410,11 @@
                                CAST_FROM_FN_PTR(address,
                                                 SharedRuntime::
                                                 throw_StackOverflowError));
+    StubRoutines::_throw_delayed_StackOverflowError_entry =
+      generate_throw_exception("delayed StackOverflowError throw_exception",
+                               CAST_FROM_FN_PTR(address,
+                                                SharedRuntime::
+                                                throw_delayed_StackOverflowError));
     if (UseCRC32Intrinsics) {
       // set table address before stub generation which use it
       StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -541,8 +541,8 @@
   __ subptr(rax, stack_size);
 
   // Use the maximum number of pages we might bang.
-  const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages) ? StackShadowPages :
-                                                                              (StackRedPages+StackYellowPages);
+  const int max_pages = StackShadowPages > (StackRedPages+StackYellowPages+StackReservedPages) ? StackShadowPages :
+                        (StackRedPages+StackYellowPages+StackReservedPages);
 
   // add in the red and yellow zone sizes
   __ addptr(rax, max_pages * page_size);
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Fri Dec 11 09:07:07 2015 -0800
@@ -670,17 +670,16 @@
 
 void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
   Compile *C = ra_->C;
+  MacroAssembler _masm(&cbuf);
 
   if (C->max_vector_size() > 16) {
     // Clear upper bits of YMM registers when current compiled code uses
     // wide vectors to avoid AVX <-> SSE transition penalty during call.
-    MacroAssembler masm(&cbuf);
-    masm.vzeroupper();
+    _masm.vzeroupper();
   }
   // If method set FPU control word, restore to standard control word
   if (C->in_24_bit_fp_mode()) {
-    MacroAssembler masm(&cbuf);
-    masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
+    _masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
   }
 
   int framesize = C->frame_size_in_bytes();
@@ -702,6 +701,10 @@
 
   emit_opcode(cbuf, 0x58 | EBP_enc);
 
+  if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+    __ reserved_stack_check();
+  }
+
   if (do_polling() && C->is_method_compilation()) {
     cbuf.relocate(cbuf.insts_end(), relocInfo::poll_return_type, 0);
     emit_opcode(cbuf,0x85);
@@ -729,6 +732,7 @@
   } else {
     size += framesize ? 3 : 0;
   }
+  size += 64; // added to support ReservedStackAccess
   return size;
 }
 
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Fri Dec 11 09:07:07 2015 -0800
@@ -953,10 +953,11 @@
 void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
 {
   Compile* C = ra_->C;
+  MacroAssembler _masm(&cbuf);
+
   if (C->max_vector_size() > 16) {
     // Clear upper bits of YMM registers when current compiled code uses
     // wide vectors to avoid AVX <-> SSE transition penalty during call.
-    MacroAssembler _masm(&cbuf);
     __ vzeroupper();
   }
 
@@ -984,6 +985,10 @@
   // popq rbp
   emit_opcode(cbuf, 0x58 | RBP_enc);
 
+  if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+    __ reserved_stack_check(); 
+  }
+
   if (do_polling() && C->is_method_compilation()) {
     MacroAssembler _masm(&cbuf);
     AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -48,14 +48,17 @@
 #define DEFAULT_STACK_YELLOW_PAGES (2)
 #define DEFAULT_STACK_RED_PAGES (1)
 #define DEFAULT_STACK_SHADOW_PAGES (5 LP64_ONLY(+1) DEBUG_ONLY(+3))
+#define DEFAULT_STACK_RESERVED_PAGES (0)
 
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
 #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
 #define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+#define MIN_STACK_RESERVED_PAGES (0)
 
 define_pd_global(intx,  StackYellowPages,     DEFAULT_STACK_YELLOW_PAGES);
 define_pd_global(intx,  StackRedPages,        DEFAULT_STACK_RED_PAGES);
 define_pd_global(intx,  StackShadowPages,     DEFAULT_STACK_SHADOW_PAGES);
+define_pd_global(intx,  StackReservedPages,   DEFAULT_STACK_RESERVED_PAGES);
 
 define_pd_global(bool,  RewriteBytecodes,     true);
 define_pd_global(bool,  RewriteFrequentPairs, true);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -170,7 +170,7 @@
      * @return flags of this method
      */
     private int getFlags() {
-        return UNSAFE.getByte(metaspaceMethod + config().methodFlagsOffset);
+        return UNSAFE.getShort(metaspaceMethod + config().methodFlagsOffset);
     }
 
     /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Dec 11 09:07:07 2015 -0800
@@ -1244,7 +1244,7 @@
     @HotSpotVMField(name = "Method::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int methodAccessFlagsOffset;
     @HotSpotVMField(name = "Method::_constMethod", type = "ConstMethod*", get = HotSpotVMField.Type.OFFSET) @Stable public int methodConstMethodOffset;
     @HotSpotVMField(name = "Method::_intrinsic_id", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodIntrinsicIdOffset;
-    @HotSpotVMField(name = "Method::_flags", type = "u1", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
+    @HotSpotVMField(name = "Method::_flags", type = "u2", get = HotSpotVMField.Type.OFFSET) @Stable public int methodFlagsOffset;
     @HotSpotVMField(name = "Method::_vtable_index", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int methodVtableIndexOffset;
 
     @HotSpotVMConstant(name = "Method::_jfr_towrite") @Stable public int methodFlagsJfrTowrite;
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -3497,7 +3497,7 @@
   // Add in 2*BytesPerWord times page size to account for VM stack during
   // class initialization depending on 32 or 64 bit VM.
   os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed,
-                                    (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+                                    (size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages+
                                     2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size());
 
   size_t threadStackSizeInBytes = ThreadStackSize * K;
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/bsd/vm/os_bsd.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -99,6 +99,8 @@
   static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
                                               intptr_t** ret_sp, intptr_t** ret_fp);
 
+  static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
+
   // This boolean allows users to forward their own non-matching signals
   // to JVM_handle_bsd_signal, harmlessly.
   static bool signal_handlers_are_installed;
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1861,8 +1861,8 @@
     JavaThread *jt = Threads::first();
 
     while (jt) {
-      if (!jt->stack_guard_zone_unused() &&        // Stack not yet fully initialized
-          jt->stack_yellow_zone_enabled()) {       // No pending stack overflow exceptions
+      if (!jt->stack_guard_zone_unused() &&     // Stack not yet fully initialized
+          jt->stack_guards_enabled()) {         // No pending stack overflow exceptions
         if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(),
                               jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) {
           warning("Attempt to reguard stack yellow zone failed.");
@@ -4603,6 +4603,11 @@
   if (vm_page_size() > (int)Linux::vm_default_page_size()) {
     StackYellowPages = 1;
     StackRedPages = 1;
+#if defined(IA32) || defined(IA64)
+    StackReservedPages = 1;
+#else
+    StackReservedPages = 0;
+#endif
     StackShadowPages = round_to((StackShadowPages*Linux::vm_default_page_size()), vm_page_size()) / vm_page_size();
   }
 
@@ -4664,7 +4669,7 @@
   // Add in 2*BytesPerWord times page size to account for VM stack during
   // class initialization depending on 32 or 64 bit VM.
   os::Linux::min_stack_allowed = MAX2(os::Linux::min_stack_allowed,
-                                      (size_t)(StackYellowPages+StackRedPages+StackShadowPages) * Linux::page_size() +
+                                      (size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages) * Linux::page_size() +
                                       (2*BytesPerWord COMPILER2_PRESENT(+1)) * Linux::vm_default_page_size());
 
   size_t threadStackSizeInBytes = ThreadStackSize * K;
--- a/hotspot/src/os/linux/vm/os_linux.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/linux/vm/os_linux.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -136,6 +136,8 @@
   static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
                                               intptr_t** ret_sp, intptr_t** ret_fp);
 
+  static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
+
   // This boolean allows users to forward their own non-matching signals
   // to JVM_handle_linux_signal, harmlessly.
   static bool signal_handlers_are_installed;
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -4382,6 +4382,7 @@
   if (vm_page_size() > 8*K) {
     StackYellowPages = 1;
     StackRedPages = 1;
+    StackReservedPages = 1;
     StackShadowPages = round_to((StackShadowPages*8*K), vm_page_size()) / vm_page_size();
   }
 }
@@ -4438,7 +4439,7 @@
   // Add in 2*BytesPerWord times page size to account for VM stack during
   // class initialization depending on 32 or 64 bit VM.
   os::Solaris::min_stack_allowed = MAX2(os::Solaris::min_stack_allowed,
-                                        (size_t)(StackYellowPages+StackRedPages+StackShadowPages+
+                                        (size_t)(StackReservedPages+StackYellowPages+StackRedPages+StackShadowPages+
                                         2*BytesPerWord COMPILER2_PRESENT(+1)) * page_size);
 
   size_t threadStackSizeInBytes = ThreadStackSize * K;
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,6 +150,8 @@
   static ExtendedPC fetch_frame_from_ucontext(Thread* thread, ucontext_t* uc,
                                               intptr_t** ret_sp, intptr_t** ret_fp);
 
+  static bool get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr);
+
   static void hotspot_sigmask(Thread* thread);
 
   // SR_handler
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -2374,6 +2374,39 @@
   // somewhere where we can find it in the minidump.
 }
 
+bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread,
+        struct _EXCEPTION_POINTERS* exceptionInfo, address pc, frame* fr) {
+  PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
+  address addr = (address) exceptionRecord->ExceptionInformation[1];
+  if (Interpreter::contains(pc)) {
+    *fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      *fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
+      // in compiled code, the stack banging is performed just after the return pc
+      // has been pushed on the stack
+      *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 //-----------------------------------------------------------------------------
 LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
   if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH;
@@ -2550,7 +2583,16 @@
                                   SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW));
         }
 #endif
-        if (thread->stack_yellow_zone_enabled()) {
+        if (thread->stack_guards_enabled()) {
+          if (_thread_in_Java) {
+            frame fr;
+            PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;
+            address addr = (address) exceptionRecord->ExceptionInformation[1];
+            if (os::win32::get_frame_at_stack_banging_point(thread, exceptionInfo, pc, &fr)) {
+              assert(fr.is_java_frame(), "Must be a Java frame");
+              SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+            }
+          }
           // Yellow zone violation.  The o/s has unprotected the first yellow
           // zone page for us.  Note:  must call disable_stack_yellow_zone to
           // update the enabled status, even if the zone contains only one page.
--- a/hotspot/src/os/windows/vm/os_windows.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os/windows/vm/os_windows.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -110,6 +110,10 @@
   // Default stack size for the current process.
   static size_t default_stack_size() { return _default_stack_size; }
 
+  static bool get_frame_at_stack_banging_point(JavaThread* thread,
+                          struct _EXCEPTION_POINTERS* exceptionInfo,
+                          address pc, frame* fr);
+
 #ifndef _WIN64
   // A wrapper to install a structured exception handler for fast JNI accesors.
   static address fast_jni_accessor_wrapper(BasicType);
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -325,6 +325,7 @@
 // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
 // frames. Currently we don't do that on Bsd, so it's the same as
 // os::fetch_frame_from_context().
+// This method is also used for stack overflow signal handling.
 ExtendedPC os::Bsd::fetch_frame_from_ucontext(Thread* thread,
   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 
@@ -362,6 +363,48 @@
   return frame(sp, fp, epc.pc());
 }
 
+frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
+  intptr_t* sp;
+  intptr_t* fp;
+  ExtendedPC epc = os::Bsd::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
+  return frame(sp, fp, epc.pc());
+}
+
+bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+  address pc = (address) os::Bsd::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    // interpreter performs stack banging after the fixed frame header has
+    // been generated while the compilers perform it before. To maintain
+    // semantic consistency between interpreted and compiled frames, the
+    // method returns the Java sender of the current frame.
+    *fr = os::fetch_frame_from_ucontext(thread, uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      *fr = os::fetch_frame_from_ucontext(thread, uc);
+      // in compiled code, the stack banging is performed just after the return pc
+      // has been pushed on the stack
+      *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 // By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
 // turned off by -fomit-frame-pointer,
 frame os::get_sender_for_C_frame(frame* fr) {
@@ -479,13 +522,31 @@
           addr >= thread->stack_base() - thread->stack_size()) {
         // stack overflow
         if (thread->in_stack_yellow_zone(addr)) {
-          thread->disable_stack_yellow_zone();
           if (thread->thread_state() == _thread_in_Java) {
+            if (thread->in_stack_reserved_zone(addr)) {
+              frame fr;
+              if (os::Bsd::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+                assert(fr.is_java_frame(), "Must be a Java frame");
+                frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+                if (activation.sp() != NULL) {
+                  thread->disable_stack_reserved_zone();
+                  if (activation.is_interpreted_frame()) {
+                    thread->set_reserved_stack_activation((address)(
+                      activation.fp() + frame::interpreter_frame_initial_sp_offset));
+                  } else {
+                    thread->set_reserved_stack_activation((address)activation.unextended_sp());
+                  }
+                  return 1;
+                }
+              }
+            }
             // Throw a stack overflow exception.  Guard pages will be reenabled
             // while unwinding the stack.
+            thread->disable_stack_yellow_zone();
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
           } else {
             // Thread was in the vm or native code.  Return and try to finish.
+            thread->disable_stack_yellow_zone();
             return 1;
           }
         } else if (thread->in_stack_red_zone(addr)) {
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -138,6 +138,7 @@
 // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
 // frames. Currently we don't do that on Linux, so it's the same as
 // os::fetch_frame_from_context().
+// This method is also used for stack overflow signal handling.
 ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 
@@ -175,6 +176,50 @@
   return frame(sp, fp, epc.pc());
 }
 
+frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
+  intptr_t* sp;
+  intptr_t* fp;
+  ExtendedPC epc = os::Linux::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
+  return frame(sp, fp, epc.pc());
+}
+
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+  address pc = (address) os::Linux::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    // interpreter performs stack banging after the fixed frame header has
+    // been generated while the compilers perform it before. To maintain
+    // semantic consistency between interpreted and compiled frames, the
+    // method returns the Java sender of the current frame.
+    *fr = os::fetch_frame_from_ucontext(thread, uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      // in compiled code, the stack banging is performed just after the return pc
+      // has been pushed on the stack
+      intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+      intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+      *fr = frame(sp + 1, fp, (address)*sp);
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        assert(!fr->is_first_frame(), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 // By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
 // turned off by -fomit-frame-pointer,
 frame os::get_sender_for_C_frame(frame* fr) {
@@ -305,13 +350,32 @@
           addr >= thread->stack_base() - thread->stack_size()) {
         // stack overflow
         if (thread->in_stack_yellow_zone(addr)) {
-          thread->disable_stack_yellow_zone();
           if (thread->thread_state() == _thread_in_Java) {
+            if (thread->in_stack_reserved_zone(addr)) {
+              frame fr;
+              if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+                assert(fr.is_java_frame(), "Must be a Java frame");
+                frame activation =
+                  SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+                if (activation.sp() != NULL) {
+                  thread->disable_stack_reserved_zone();
+                  if (activation.is_interpreted_frame()) {
+                    thread->set_reserved_stack_activation((address)(
+                      activation.fp() + frame::interpreter_frame_initial_sp_offset));
+                  } else {
+                    thread->set_reserved_stack_activation((address)activation.unextended_sp());
+                  }
+                  return 1;
+                }
+              }
+            }
             // Throw a stack overflow exception.  Guard pages will be reenabled
             // while unwinding the stack.
+            thread->disable_stack_yellow_zone();
             stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
           } else {
             // Thread was in the vm or native code.  Return and try to finish.
+            thread->disable_stack_yellow_zone();
             return 1;
           }
         } else if (thread->in_stack_red_zone(addr)) {
@@ -868,7 +932,7 @@
    * we don't have much control or understanding of the address space, just let it slide.
    */
   char* hint = (char*) (Linux::initial_thread_stack_bottom() -
-                        ((StackYellowPages + StackRedPages + 1) * page_size));
+                        ((StackReservedPages + StackYellowPages + StackRedPages + 1) * page_size));
   char* codebuf = os::attempt_reserve_memory_at(page_size, hint);
   if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) {
     return; // No matter, we tried, best effort.
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -213,6 +213,7 @@
 //
 // The difference between this and os::fetch_frame_from_context() is that
 // here we try to skip nested signal frames.
+// This method is also used for stack overflow signal handling.
 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 
@@ -252,6 +253,41 @@
   return frame(sp, frame::unpatchable, epc.pc());
 }
 
+frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
+  intptr_t* sp;
+  ExtendedPC epc = os::Solaris::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, NULL);
+  return frame(sp, frame::unpatchable, epc.pc());
+}
+
+bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+  address pc = (address) os::Solaris::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    *fr = os::fetch_frame_from_ucontext(thread, uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      *fr = os::fetch_frame_from_ucontext(thread, uc);
+      *fr = frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 frame os::get_sender_for_C_frame(frame* fr) {
   return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
 }
@@ -367,17 +403,32 @@
     if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
       address addr = (address) info->si_addr;
       if (thread->in_stack_yellow_zone(addr)) {
-        thread->disable_stack_yellow_zone();
         // Sometimes the register windows are not properly flushed.
         if(uc->uc_mcontext.gwins != NULL) {
           ::handle_unflushed_register_windows(uc->uc_mcontext.gwins);
         }
         if (thread->thread_state() == _thread_in_Java) {
+          if (thread->in_stack_reserved_zone(addr)) {
+            frame fr;
+            if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+              assert(fr.is_java_frame(), "Must be a Java frame");
+              frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+              if (activation.sp() != NULL) {
+                thread->disable_stack_reserved_zone();
+                RegisterMap map(thread);
+                int frame_size = activation.frame_size(&map);
+                thread->set_reserved_stack_activation((address)(((address)activation.sp()) - STACK_BIAS));
+                return true;
+              }
+            }
+          }
           // Throw a stack overflow exception.  Guard pages will be reenabled
           // while unwinding the stack.
+          thread->disable_stack_yellow_zone();
           stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
         } else {
           // Thread was in the vm or native code.  Return and try to finish.
+          thread->disable_stack_yellow_zone();
           return true;
         }
       } else if (thread->in_stack_red_zone(addr)) {
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -198,6 +198,7 @@
 //
 // The difference between this and os::fetch_frame_from_context() is that
 // here we try to skip nested signal frames.
+// This method is also used for stack overflow signal handling.
 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
   ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
 
@@ -236,6 +237,49 @@
   return frame(sp, fp, epc.pc());
 }
 
+frame os::fetch_frame_from_ucontext(Thread* thread, void* ucVoid) {
+  intptr_t* sp;
+  intptr_t* fp;
+  ExtendedPC epc = os::Solaris::fetch_frame_from_ucontext(thread, (ucontext_t*)ucVoid, &sp, &fp);
+  return frame(sp, fp, epc.pc());
+}
+
+bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+ address pc = (address) os::Solaris::ucontext_get_pc(uc);
+  if (Interpreter::contains(pc)) {
+    // interpreter performs stack banging after the fixed frame header has
+    // been generated while the compilers perform it before. To maintain
+    // semantic consistency between interpreted and compiled frames, the
+    // method returns the Java sender of the current frame.
+    *fr = os::fetch_frame_from_ucontext(thread, uc);
+    if (!fr->is_first_java_frame()) {
+      assert(fr->safe_for_sender(thread), "Safety check");
+      *fr = fr->java_sender();
+    }
+  } else {
+    // more complex code with compiled code
+    assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+      // Not sure where the pc points to, fallback to default
+      // stack overflow handling
+      return false;
+    } else {
+      // in compiled code, the stack banging is performed just after the return pc
+      // has been pushed on the stack
+      intptr_t* fp = os::Solaris::ucontext_get_fp(uc);
+      intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
+      *fr = frame(sp + 1, fp, (address)*sp);
+      if (!fr->is_java_frame()) {
+        assert(fr->safe_for_sender(thread), "Safety check");
+        *fr = fr->java_sender();
+      }
+    }
+  }
+  assert(fr->is_java_frame(), "Safety check");
+  return true;
+}
+
 frame os::get_sender_for_C_frame(frame* fr) {
   return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
 }
@@ -422,13 +466,31 @@
     if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
       address addr = (address) info->si_addr;
       if (thread->in_stack_yellow_zone(addr)) {
-        thread->disable_stack_yellow_zone();
         if (thread->thread_state() == _thread_in_Java) {
+          if (thread->in_stack_reserved_zone(addr)) {
+            frame fr;
+            if (os::Solaris::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+              assert(fr.is_java_frame(), "Must be Java frame");
+              frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+              if (activation.sp() != NULL) {
+                thread->disable_stack_reserved_zone();
+                if (activation.is_interpreted_frame()) {
+                  thread->set_reserved_stack_activation((address)(
+                    activation.fp() + frame::interpreter_frame_initial_sp_offset));
+                } else {
+                  thread->set_reserved_stack_activation((address)activation.unextended_sp());
+                }
+                return true;
+              }
+            }
+          }
           // Throw a stack overflow exception.  Guard pages will be reenabled
           // while unwinding the stack.
+          thread->disable_stack_yellow_zone();
           stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
         } else {
           // Thread was in the vm or native code.  Return and try to finish.
+          thread->disable_stack_yellow_zone();
           return true;
         }
       } else if (thread->in_stack_red_zone(addr)) {
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -551,6 +551,7 @@
 , _would_profile(false)
 , _has_unsafe_access(false)
 , _has_method_handle_invokes(false)
+, _has_reserved_stack_access(method->has_reserved_stack_access())
 , _bailout_msg(NULL)
 , _exception_info_list(NULL)
 , _allocator(NULL)
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@
   bool               _has_unsafe_access;
   bool               _would_profile;
   bool               _has_method_handle_invokes;  // True if this method has MethodHandle invokes.
+  bool               _has_reserved_stack_access;
   const char*        _bailout_msg;
   ExceptionInfoList* _exception_info_list;
   ExceptionHandlerTable _exception_handler_table;
@@ -171,6 +172,9 @@
   bool     has_method_handle_invokes() const { return _has_method_handle_invokes;     }
   void set_has_method_handle_invokes(bool z) {        _has_method_handle_invokes = z; }
 
+  bool     has_reserved_stack_access() const { return _has_reserved_stack_access; }
+  void set_has_reserved_stack_access(bool z) { _has_reserved_stack_access = z; }
+
   DebugInformationRecorder* debug_info_recorder() const; // = _env->debug_info();
   Dependencies* dependency_recorder() const; // = _env->dependencies()
   ImplicitExceptionTable* implicit_exception_table()     { return &_implicit_exception_table; }
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -3322,7 +3322,13 @@
 
   // method handle invokes
   if (callee->is_method_handle_intrinsic()) {
-    return try_method_handle_inline(callee);
+    if (try_method_handle_inline(callee)) {
+      if (callee->has_reserved_stack_access()) {
+        compilation()->set_has_reserved_stack_access(true);
+      }
+      return true;
+    }
+    return false;
   }
 
   // handle intrinsics
@@ -3330,6 +3336,9 @@
       (CheckIntrinsics ? callee->intrinsic_candidate() : true)) {
     if (try_inline_intrinsics(callee)) {
       print_inlining(callee, "intrinsic");
+      if (callee->has_reserved_stack_access()) {
+        compilation()->set_has_reserved_stack_access(true);
+      }
       return true;
     }
     // try normal inlining
@@ -3346,8 +3355,12 @@
   if (bc == Bytecodes::_illegal) {
     bc = code();
   }
-  if (try_inline_full(callee, holder_known, bc, receiver))
+  if (try_inline_full(callee, holder_known, bc, receiver)) {
+    if (callee->has_reserved_stack_access()) {
+      compilation()->set_has_reserved_stack_access(true);
+    }
     return true;
+  }
 
   // Entire compilation could fail during try_inline_full call.
   // In that case printing inlining decision info is useless.
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -502,7 +502,7 @@
   // Check the stack guard pages and reenable them if necessary and there is
   // enough space on the stack to do so.  Use fast exceptions only if the guard
   // pages are enabled.
-  bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+  bool guard_pages_enabled = thread->stack_guards_enabled();
   if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
 
   if (JvmtiExport::can_post_on_exceptions()) {
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -91,6 +91,7 @@
   _balanced_monitors  = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
   _is_c1_compilable   = !h_m()->is_not_c1_compilable();
   _is_c2_compilable   = !h_m()->is_not_c2_compilable();
+  _has_reserved_stack_access = h_m()->has_reserved_stack_access();
   // Lazy fields, filled in on demand.  Require allocation.
   _code               = NULL;
   _exception_handlers = NULL;
--- a/hotspot/src/share/vm/ci/ciMethod.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@
   bool _is_c1_compilable;
   bool _is_c2_compilable;
   bool _can_be_statically_bound;
+  bool _has_reserved_stack_access;
 
   // Lazy fields, filled in on demand
   address              _code;
@@ -316,6 +317,7 @@
   bool is_accessor    () const;
   bool is_initializer () const;
   bool can_be_statically_bound() const           { return _can_be_statically_bound; }
+  bool has_reserved_stack_access() const         { return _has_reserved_stack_access; }
   bool is_boxing_method() const;
   bool is_unboxing_method() const;
 
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -946,6 +946,7 @@
     _method_HotSpotIntrinsicCandidate,
     _jdk_internal_vm_annotation_Contended,
     _field_Stable,
+    _jdk_internal_vm_annotation_ReservedStackAccess,
     _annotation_LIMIT
   };
   const Location _location;
@@ -2016,6 +2017,11 @@
       }
       return _jdk_internal_vm_annotation_Contended;
     }
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ReservedStackAccess_signature): {
+      if (_location != _in_method)  break;  // only allow for methods
+      if (RestrictReservedStack && !privileged) break; // honor privileges
+      return _jdk_internal_vm_annotation_ReservedStackAccess;
+    }
     default: {
       break;
     }
@@ -2051,6 +2057,8 @@
     m->set_hidden(true);
   if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic())
     m->set_intrinsic_candidate(true);
+  if (has_annotation(_jdk_internal_vm_annotation_ReservedStackAccess))
+    m->set_has_reserved_stack_access(true);
 }
 
 void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -212,6 +212,7 @@
   template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
   template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl,     "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
   template(jdk_internal_vm_annotation_Contended_signature,                   "Ljdk/internal/vm/annotation/Contended;")    \
+  template(jdk_internal_vm_annotation_ReservedStackAccess_signature,         "Ljdk/internal/vm/annotation/ReservedStackAccess;") \
                                                                                                   \
   /* class symbols needed by intrinsics */                                                        \
   VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -314,6 +314,27 @@
   THROW_HANDLE(exception);
 IRT_END
 
+IRT_ENTRY(address, InterpreterRuntime::check_ReservedStackAccess_annotated_methods(JavaThread* thread))
+  frame fr = thread->last_frame();
+  assert(fr.is_java_frame(), "Must be a Java frame");
+  frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+  if (activation.sp() != NULL) {
+    thread->disable_stack_reserved_zone();
+    thread->set_reserved_stack_activation((address)activation.unextended_sp());
+  }
+  return (address)activation.sp();
+IRT_END
+
+ IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread))
+  Handle exception = get_preinitialized_exception(
+                                 SystemDictionary::StackOverflowError_klass(),
+                                 CHECK);
+  java_lang_Throwable::set_message(exception(),
+          Universe::delayed_stack_overflow_error_message());
+  // Increment counter for hs_err file reporting
+  Atomic::inc(&Exceptions::_stack_overflow_errors);
+  THROW_HANDLE(exception);
+IRT_END
 
 IRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* thread, char* name, char* message))
   // lookup exception klass
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -91,10 +91,13 @@
   // Quicken instance-of and check-cast bytecodes
   static void    quicken_io_cc(JavaThread* thread);
 
+  static address check_ReservedStackAccess_annotated_methods(JavaThread* thread);
+
   // Exceptions thrown by the interpreter
   static void    throw_AbstractMethodError(JavaThread* thread);
   static void    throw_IncompatibleClassChangeError(JavaThread* thread);
   static void    throw_StackOverflowError(JavaThread* thread);
+  static void    throw_delayed_StackOverflowError(JavaThread* thread);
   static void    throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
   static void    throw_ClassCastException(JavaThread* thread, oopDesc* obj);
   static void    create_exception(JavaThread* thread, char* name, char* message);
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -248,7 +248,7 @@
   // Check the stack guard pages and reenable them if necessary and there is
   // enough space on the stack to do so.  Use fast exceptions only if the guard
   // pages are enabled.
-  bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+  bool guard_pages_enabled = thread->stack_guards_enabled();
   if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
 
   if (JvmtiExport::can_post_on_exceptions()) {
--- a/hotspot/src/share/vm/memory/universe.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/memory/universe.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -125,6 +125,7 @@
 oop Universe::_out_of_memory_error_array_size         = NULL;
 oop Universe::_out_of_memory_error_gc_overhead_limit  = NULL;
 oop Universe::_out_of_memory_error_realloc_objects    = NULL;
+oop Universe::_delayed_stack_overflow_error_message   = NULL;
 objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
 volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
 bool Universe::_verify_in_progress                    = false;
@@ -200,7 +201,8 @@
   f->do_oop((oop*)&_out_of_memory_error_array_size);
   f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit);
   f->do_oop((oop*)&_out_of_memory_error_realloc_objects);
-    f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
+  f->do_oop((oop*)&_delayed_stack_overflow_error_message);
+  f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
   f->do_oop((oop*)&_null_ptr_exception_instance);
   f->do_oop((oop*)&_arithmetic_exception_instance);
   f->do_oop((oop*)&_virtual_machine_error_instance);
@@ -909,6 +911,12 @@
       k_h->allocate_instance(CHECK_false);
     Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
 
+    // Setup preallocated cause message for delayed StackOverflowError
+    if (StackReservedPages > 0) {
+      Universe::_delayed_stack_overflow_error_message =
+        java_lang_String::create_oop_from_str("Delayed StackOverflowError due to ReservedStackAccess annotated method", CHECK_false);
+    }
+
     // Setup preallocated NullPointerException
     // (this is currently used for a cheap & dirty solution in compiler exception handling)
     k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
--- a/hotspot/src/share/vm/memory/universe.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/memory/universe.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -159,6 +159,9 @@
   static oop          _out_of_memory_error_gc_overhead_limit;
   static oop          _out_of_memory_error_realloc_objects;
 
+  // preallocated cause message for delayed StackOverflowError
+  static oop          _delayed_stack_overflow_error_message;
+
   static Array<int>*       _the_empty_int_array;    // Canonicalized int array
   static Array<u2>*        _the_empty_short_array;  // Canonicalized short array
   static Array<Klass*>*  _the_empty_klass_array;  // Canonicalized klass obj array
@@ -339,6 +342,7 @@
   static oop out_of_memory_error_array_size()         { return gen_out_of_memory_error(_out_of_memory_error_array_size); }
   static oop out_of_memory_error_gc_overhead_limit()  { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit);  }
   static oop out_of_memory_error_realloc_objects()    { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects);  }
+  static oop delayed_stack_overflow_error_message()   { return _delayed_stack_overflow_error_message; }
 
   // Accessors needed for fast allocation
   static Klass** boolArrayKlassObj_addr()           { return &_boolArrayKlassObj;   }
--- a/hotspot/src/share/vm/oops/method.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/oops/method.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -75,16 +75,17 @@
 
   // Flags
   enum Flags {
-    _jfr_towrite          = 1 << 0,
-    _caller_sensitive     = 1 << 1,
-    _force_inline         = 1 << 2,
-    _dont_inline          = 1 << 3,
-    _hidden               = 1 << 4,
-    _has_injected_profile = 1 << 5,
-    _running_emcp         = 1 << 6,
-    _intrinsic_candidate  = 1 << 7
+    _jfr_towrite           = 1 << 0,
+    _caller_sensitive      = 1 << 1,
+    _force_inline          = 1 << 2,
+    _dont_inline           = 1 << 3,
+    _hidden                = 1 << 4,
+    _has_injected_profile  = 1 << 5,
+    _running_emcp          = 1 << 6,
+    _intrinsic_candidate   = 1 << 7,
+    _reserved_stack_access = 1 << 8
   };
-  mutable u1 _flags;
+  mutable u2 _flags;
 
 #ifndef PRODUCT
   int               _compiled_invocation_count;  // Number of nmethod invocations so far (for perf. debugging)
@@ -835,6 +836,14 @@
     _flags = x ? (_flags | _has_injected_profile) : (_flags & ~_has_injected_profile);
   }
 
+  bool has_reserved_stack_access() {
+    return (_flags & _reserved_stack_access) != 0;
+  }
+
+  void set_has_reserved_stack_access(bool x) {
+    _flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access);
+  }
+
   ConstMethod::MethodType method_type() const {
       return _constMethod->method_type();
   }
--- a/hotspot/src/share/vm/opto/compile.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/opto/compile.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -672,7 +672,8 @@
                   _print_inlining_idx(0),
                   _print_inlining_output(NULL),
                   _interpreter_frame_size(0),
-                  _max_node_limit(MaxNodeLimit) {
+                  _max_node_limit(MaxNodeLimit),
+                  _has_reserved_stack_access(target->has_reserved_stack_access()) {
   C = this;
 #ifndef PRODUCT
   if (_printer != NULL) {
--- a/hotspot/src/share/vm/opto/compile.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/opto/compile.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -364,6 +364,7 @@
   bool                  _has_unsafe_access;     // True if the method _may_ produce faults in unsafe loads or stores.
   bool                  _has_stringbuilder;     // True StringBuffers or StringBuilders are allocated
   bool                  _has_boxed_value;       // True if a boxed object is allocated
+  bool                  _has_reserved_stack_access; // True if the method or an inlined method is annotated with ReservedStackAccess
   int                   _max_vector_size;       // Maximum size of generated vectors
   uint                  _trap_hist[trapHistLength];  // Cumulative traps
   bool                  _trap_can_recompile;    // Have we emitted a recompiling trap?
@@ -637,6 +638,8 @@
   void          set_has_stringbuilder(bool z)   { _has_stringbuilder = z; }
   bool              has_boxed_value() const     { return _has_boxed_value; }
   void          set_has_boxed_value(bool z)     { _has_boxed_value = z; }
+  bool              has_reserved_stack_access() const { return _has_reserved_stack_access; }
+  void          set_has_reserved_stack_access(bool z) { _has_reserved_stack_access = z; }
   int               max_vector_size() const     { return _max_vector_size; }
   void          set_max_vector_size(int s)      { _max_vector_size = s; }
   void          set_trap_count(uint r, uint c)  { assert(r < trapHistLength, "oob");        _trap_hist[r] = c; }
--- a/hotspot/src/share/vm/opto/parse1.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -415,6 +415,10 @@
   _est_switch_depth = 0;
 #endif
 
+  if (parse_method->has_reserved_stack_access()) {
+    C->set_has_reserved_stack_access(true);
+  }
+
   _tf = TypeFunc::make(method());
   _iter.reset_to_method(method());
   _flow = method()->get_flow_analysis();
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -2426,6 +2426,12 @@
     warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
   }
 
+#ifndef SUPPORT_RESERVED_STACK_AREA
+  if (StackReservedPages != 0) {
+    FLAG_SET_CMDLINE(intx, StackReservedPages, 0);
+    warning("Reserved Stack Area not supported on this platform");
+  }
+#endif
   return status;
 }
 
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1431,7 +1431,7 @@
     // stack bang causes a stack overflow we crash.
     assert(THREAD->is_Java_thread(), "only a java thread can be here");
     JavaThread* thread = (JavaThread*)THREAD;
-    bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+    bool guard_pages_enabled = thread->stack_guards_enabled();
     if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
     assert(guard_pages_enabled, "stack banging in uncommon trap blob may cause crash");
   }
--- a/hotspot/src/share/vm/runtime/globals.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -3438,6 +3438,13 @@
           "Number of red zone (unrecoverable overflows) pages")             \
           range(MIN_STACK_RED_PAGES, (DEFAULT_STACK_RED_PAGES+2))           \
                                                                             \
+  product_pd(intx, StackReservedPages,                                      \
+          "Number of reserved zone (reserved to annotated methods) pages")  \
+          range(MIN_STACK_RESERVED_PAGES, (DEFAULT_STACK_RESERVED_PAGES+10))\
+                                                                            \
+  product(bool, RestrictReservedStack, true,                                \
+          "Restrict @ReservedStackAccess to trusted classes")               \
+                                                                            \
   /* greater stack shadow pages can't generate instruction to bang stack */ \
   product_pd(intx, StackShadowPages,                                        \
           "Number of shadow zone (for overflow checking) pages "            \
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -371,9 +371,9 @@
   // Find receiver
   Handle receiver = (!method->is_static()) ? args->receiver() : Handle();
 
-  // When we reenter Java, we need to reenable the yellow zone which
+  // When we reenter Java, we need to reenable the reserved/yellow zone which
   // might already be disabled when we are in VM.
-  if (thread->stack_yellow_zone_disabled()) {
+  if (!thread->stack_guards_enabled()) {
     thread->reguard_stack();
   }
 
--- a/hotspot/src/share/vm/runtime/os.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/os.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1386,8 +1386,9 @@
   // respectively.
   const int framesize_in_bytes =
     Interpreter::size_top_interpreter_activation(method()) * wordSize;
-  int reserved_area = ((StackShadowPages + StackRedPages + StackYellowPages)
-                      * vm_page_size()) + framesize_in_bytes;
+  int reserved_area = ((StackShadowPages + StackRedPages + StackYellowPages
+                      + StackReservedPages) * vm_page_size())
+                      + framesize_in_bytes;
   // The very lower end of the stack
   address stack_limit = thread->stack_base() - thread->stack_size();
   return (sp > (stack_limit + reserved_area));
--- a/hotspot/src/share/vm/runtime/os.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/os.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -473,6 +473,7 @@
 
   static ExtendedPC fetch_frame_from_context(void* ucVoid, intptr_t** sp, intptr_t** fp);
   static frame      fetch_frame_from_context(void* ucVoid);
+  static frame      fetch_frame_from_ucontext(Thread* thread, void* ucVoid);
 
   static ExtendedPC get_thread_pc(Thread *thread);
   static void breakpoint();
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -57,6 +57,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframeArray.hpp"
+#include "trace/tracing.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
@@ -487,8 +488,11 @@
       // unguarded. Reguard the stack otherwise if we return to the
       // deopt blob and the stack bang causes a stack overflow we
       // crash.
-      bool guard_pages_enabled = thread->stack_yellow_zone_enabled();
+      bool guard_pages_enabled = thread->stack_guards_enabled();
       if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack();
+      if (thread->reserved_stack_activation() != thread->stack_base()) {
+        thread->set_reserved_stack_activation(thread->stack_base());
+      }
       assert(guard_pages_enabled, "stack banging in deopt blob may cause crash");
       return SharedRuntime::deopt_blob()->unpack_with_exception();
     } else {
@@ -761,10 +765,23 @@
 JRT_END
 
 JRT_ENTRY(void, SharedRuntime::throw_StackOverflowError(JavaThread* thread))
+  throw_StackOverflowError_common(thread, false);
+JRT_END
+
+JRT_ENTRY(void, SharedRuntime::throw_delayed_StackOverflowError(JavaThread* thread))
+  throw_StackOverflowError_common(thread, true);
+JRT_END
+
+void SharedRuntime::throw_StackOverflowError_common(JavaThread* thread, bool delayed) {
   // We avoid using the normal exception construction in this case because
   // it performs an upcall to Java, and we're already out of stack space.
+  Thread* THREAD = thread;
   Klass* k = SystemDictionary::StackOverflowError_klass();
   oop exception_oop = InstanceKlass::cast(k)->allocate_instance(CHECK);
+  if (delayed) {
+    java_lang_Throwable::set_message(exception_oop,
+                                     Universe::delayed_stack_overflow_error_message());
+  }
   Handle exception (thread, exception_oop);
   if (StackTraceInThrowable) {
     java_lang_Throwable::fill_in_stack_trace(exception);
@@ -772,7 +789,7 @@
   // Increment counter for hs_err file reporting
   Atomic::inc(&Exceptions::_stack_overflow_errors);
   throw_and_post_jvmti_exception(thread, exception);
-JRT_END
+}
 
 #if INCLUDE_JVMCI
 address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) {
@@ -2934,3 +2951,68 @@
 }
 
 #endif /* PRODUCT */
+
+JRT_LEAF(void, SharedRuntime::enable_stack_reserved_zone(JavaThread* thread))
+  assert(thread->is_Java_thread(), "Only Java threads have a stack reserved zone");
+  thread->enable_stack_reserved_zone();
+  thread->set_reserved_stack_activation(thread->stack_base());
+JRT_END
+
+frame SharedRuntime::look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr) {
+  frame activation;
+  int decode_offset = 0;
+  nmethod* nm = NULL;
+  frame prv_fr = fr;
+  int count = 1;
+
+  assert(fr.is_java_frame(), "Must start on Java frame");
+
+  while (!fr.is_first_frame()) {
+    Method* method = NULL;
+    // Compiled java method case.
+    if (decode_offset != 0) {
+      DebugInfoReadStream stream(nm, decode_offset);
+      decode_offset = stream.read_int();
+      method = (Method*)nm->metadata_at(stream.read_int());
+    } else {
+      if (fr.is_first_java_frame()) break;
+      address pc = fr.pc();
+      prv_fr = fr;
+      if (fr.is_interpreted_frame()) {
+        method = fr.interpreter_frame_method();
+        fr = fr.java_sender();
+      } else {
+        CodeBlob* cb = fr.cb();
+        fr = fr.java_sender();
+        if (cb == NULL || !cb->is_nmethod()) {
+          continue;
+        }
+        nm = (nmethod*)cb;
+        if (nm->method()->is_native()) {
+          method = nm->method();
+        } else {
+          PcDesc* pd = nm->pc_desc_at(pc);
+          assert(pd != NULL, "PcDesc must not be NULL");
+          decode_offset = pd->scope_decode_offset();
+          // if decode_offset is not equal to 0, it will execute the
+          // "compiled java method case" at the beginning of the loop.
+          continue;
+        }
+      }
+    }
+    if (method->has_reserved_stack_access()) {
+      ResourceMark rm(thread);
+      activation = prv_fr;
+      warning("Potentially dangerous stack overflow in "
+              "ReservedStackAccess annotated method %s [%d]",
+              method->name_and_sig_as_C_string(), count++);
+      EventReservedStackActivation event;
+      if (event.should_commit()) {
+        event.set_method(method);
+        event.commit();
+      }
+    }
+  }
+  return activation;
+}
+
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -201,6 +201,8 @@
   static void    throw_NullPointerException(JavaThread* thread);
   static void    throw_NullPointerException_at_call(JavaThread* thread);
   static void    throw_StackOverflowError(JavaThread* thread);
+  static void    throw_delayed_StackOverflowError(JavaThread* thread);
+  static void    throw_StackOverflowError_common(JavaThread* thread, bool delayed);
   static address continuation_for_implicit_exception(JavaThread* thread,
                                                      address faulting_pc,
                                                      ImplicitExceptionKind exception_kind);
@@ -208,6 +210,9 @@
   static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason);
 #endif
 
+  static void enable_stack_reserved_zone(JavaThread* thread);
+  static frame look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr);
+
   // Shared stub locations
   static address get_poll_stub(address pc);
 
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -54,6 +54,7 @@
 address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
 address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
 address StubRoutines::_throw_StackOverflowError_entry           = NULL;
+address StubRoutines::_throw_delayed_StackOverflowError_entry   = NULL;
 address StubRoutines::_handler_for_unsafe_access_entry          = NULL;
 jint    StubRoutines::_verify_oop_count                         = 0;
 address StubRoutines::_verify_oop_subroutine_entry              = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -111,6 +111,7 @@
   static address _throw_IncompatibleClassChangeError_entry;
   static address _throw_NullPointerException_at_call_entry;
   static address _throw_StackOverflowError_entry;
+  static address _throw_delayed_StackOverflowError_entry;
   static address _handler_for_unsafe_access_entry;
 
   static address _atomic_xchg_entry;
@@ -275,6 +276,7 @@
   static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; }
   static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; }
   static address throw_StackOverflowError_entry()          { return _throw_StackOverflowError_entry; }
+  static address throw_delayed_StackOverflowError_entry()  { return _throw_delayed_StackOverflowError_entry; }
 
   // Exceptions during unsafe access - should throw Java exception rather
   // than crash.
--- a/hotspot/src/share/vm/runtime/thread.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -307,6 +307,7 @@
   set_stack_size(os::current_stack_size());
   if (is_Java_thread()) {
     ((JavaThread*) this)->set_stack_overflow_limit();
+    ((JavaThread*) this)->set_reserved_stack_activation(stack_base());
   }
   // CR 7190089: on Solaris, primordial thread's stack is adjusted
   // in initialize_thread(). Without the adjustment, stack size is
@@ -908,7 +909,7 @@
 
 
 bool Thread::is_in_usable_stack(address adr) const {
-  size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0;
+  size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackReservedPages + StackYellowPages + StackRedPages) * os::vm_page_size() : 0;
   size_t usable_stack_size = _stack_size - stack_guard_size;
 
   return ((adr < stack_base()) && (adr >= stack_base() - usable_stack_size));
@@ -1460,6 +1461,7 @@
     _jvmci_counters = NULL;
   }
 #endif // INCLUDE_JVMCI
+  _reserved_stack_activation = NULL;  // stack base not known yet
   (void)const_cast<oop&>(_exception_oop = oop(NULL));
   _exception_pc  = 0;
   _exception_handler_pc = 0;
@@ -1532,7 +1534,8 @@
 }
 
 bool JavaThread::reguard_stack(address cur_sp) {
-  if (_stack_guard_state != stack_guard_yellow_disabled) {
+  if (_stack_guard_state != stack_guard_yellow_disabled
+      && _stack_guard_state != stack_guard_reserved_disabled) {
     return true; // Stack already guarded or guard pages not needed.
   }
 
@@ -1549,8 +1552,15 @@
   // some exception code in c1, c2 or the interpreter isn't unwinding
   // when it should.
   guarantee(cur_sp > stack_yellow_zone_base(), "not enough space to reguard - increase StackShadowPages");
-
-  enable_stack_yellow_zone();
+  if (_stack_guard_state == stack_guard_yellow_disabled) {
+    enable_stack_yellow_zone();
+    if (reserved_stack_activation() != stack_base()) {
+      set_reserved_stack_activation(stack_base());
+    }
+  } else if (_stack_guard_state == stack_guard_reserved_disabled) {
+    set_reserved_stack_activation(stack_base());
+    enable_stack_reserved_zone();
+  }
   return true;
 }
 
@@ -2473,7 +2483,7 @@
 void JavaThread::create_stack_guard_pages() {
   if (! os::uses_stack_guard_pages() || _stack_guard_state != stack_guard_unused) return;
   address low_addr = stack_base() - stack_size();
-  size_t len = (StackYellowPages + StackRedPages) * os::vm_page_size();
+  size_t len = (StackReservedPages + StackYellowPages + StackRedPages) * os::vm_page_size();
 
   int allocate = os::allocate_stack_guard_pages();
   // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len);
@@ -2497,7 +2507,7 @@
   assert(Thread::current() == this, "from different thread");
   if (_stack_guard_state == stack_guard_unused) return;
   address low_addr = stack_base() - stack_size();
-  size_t len = (StackYellowPages + StackRedPages) * os::vm_page_size();
+  size_t len = (StackReservedPages + StackYellowPages + StackRedPages) * os::vm_page_size();
 
   if (os::allocate_stack_guard_pages()) {
     if (os::remove_stack_guard_pages((char *) low_addr, len)) {
@@ -2515,6 +2525,44 @@
   }
 }
 
+void JavaThread::enable_stack_reserved_zone() {
+  assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
+  assert(_stack_guard_state != stack_guard_enabled, "already enabled");
+
+  // The base notation is from the stack's point of view, growing downward.
+  // We need to adjust it to work correctly with guard_memory()
+  address base = stack_reserved_zone_base() - stack_reserved_zone_size();
+
+  guarantee(base < stack_base(),"Error calculating stack reserved zone");
+  guarantee(base < os::current_stack_pointer(),"Error calculating stack reserved zone");
+
+  if (os::guard_memory((char *) base, stack_reserved_zone_size())) {
+    _stack_guard_state = stack_guard_enabled;
+  } else {
+    warning("Attempt to guard stack reserved zone failed.");
+  }
+  enable_register_stack_guard();
+}
+
+void JavaThread::disable_stack_reserved_zone() {
+  assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
+  assert(_stack_guard_state != stack_guard_reserved_disabled, "already disabled");
+
+  // Simply return if called for a thread that does not use guard pages.
+  if (_stack_guard_state == stack_guard_unused) return;
+
+  // The base notation is from the stack's point of view, growing downward.
+  // We need to adjust it to work correctly with guard_memory()
+  address base = stack_reserved_zone_base() - stack_reserved_zone_size();
+
+  if (os::unguard_memory((char *)base, stack_reserved_zone_size())) {
+    _stack_guard_state = stack_guard_reserved_disabled;
+  } else {
+    warning("Attempt to unguard stack reserved zone failed.");
+  }
+  disable_register_stack_guard();
+}
+
 void JavaThread::enable_stack_yellow_zone() {
   assert(_stack_guard_state != stack_guard_unused, "must be using guard pages.");
   assert(_stack_guard_state != stack_guard_enabled, "already enabled");
--- a/hotspot/src/share/vm/runtime/thread.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -909,6 +909,7 @@
   // State of the stack guard pages for this thread.
   enum StackGuardState {
     stack_guard_unused,         // not needed
+    stack_guard_reserved_disabled,
     stack_guard_yellow_disabled,// disabled (temporarily) after stack overflow
     stack_guard_enabled         // enabled
   };
@@ -957,6 +958,7 @@
   // Precompute the limit of the stack as used in stack overflow checks.
   // We load it from here to simplify the stack overflow check in assembly.
   address          _stack_overflow_limit;
+  address          _reserved_stack_activation;
 
   // Compiler exception handling (NOTE: The _exception_oop is *NOT* the same as _pending_exception. It is
   // used to temp. parsing values into and out of the runtime system during exception handling for compiled
@@ -1343,18 +1345,25 @@
 
   // Stack overflow support
   inline size_t stack_available(address cur_sp);
+  address stack_reserved_zone_base() {
+    return stack_yellow_zone_base(); }
+  size_t stack_reserved_zone_size() {
+    return StackReservedPages * os::vm_page_size(); }
   address stack_yellow_zone_base() {
     return (address)(stack_base() -
                      (stack_size() -
                      (stack_red_zone_size() + stack_yellow_zone_size())));
   }
   size_t  stack_yellow_zone_size() {
-    return StackYellowPages * os::vm_page_size();
+    return StackYellowPages * os::vm_page_size() + stack_reserved_zone_size();
   }
   address stack_red_zone_base() {
     return (address)(stack_base() - (stack_size() - stack_red_zone_size()));
   }
   size_t stack_red_zone_size() { return StackRedPages * os::vm_page_size(); }
+  bool in_stack_reserved_zone(address a) {
+    return (a <= stack_reserved_zone_base()) && (a >= (address)((intptr_t)stack_reserved_zone_base() - stack_reserved_zone_size()));
+  }
   bool in_stack_yellow_zone(address a) {
     return (a <= stack_yellow_zone_base()) && (a >= stack_red_zone_base());
   }
@@ -1366,6 +1375,8 @@
   void create_stack_guard_pages();
   void remove_stack_guard_pages();
 
+  void enable_stack_reserved_zone();
+  void disable_stack_reserved_zone();
   void enable_stack_yellow_zone();
   void disable_stack_yellow_zone();
   void enable_stack_red_zone();
@@ -1373,7 +1384,16 @@
 
   inline bool stack_guard_zone_unused();
   inline bool stack_yellow_zone_disabled();
-  inline bool stack_yellow_zone_enabled();
+  inline bool stack_reserved_zone_disabled();
+  inline bool stack_guards_enabled();
+
+  address reserved_stack_activation() const { return _reserved_stack_activation; }
+  void      set_reserved_stack_activation(address addr) {
+    assert(_reserved_stack_activation == stack_base()
+            || _reserved_stack_activation == NULL
+            || addr == stack_base(), "Must not be set twice");
+    _reserved_stack_activation = addr;
+  }
 
   // Attempt to reguard the stack after a stack overflow may have occurred.
   // Returns true if (a) guard pages are not needed on this thread, (b) the
@@ -1390,6 +1410,7 @@
   void set_stack_overflow_limit() {
     _stack_overflow_limit = _stack_base - _stack_size +
                             ((StackShadowPages +
+                              StackReservedPages +
                               StackYellowPages +
                               StackRedPages) * os::vm_page_size());
   }
@@ -1439,6 +1460,7 @@
   static ByteSize stack_overflow_limit_offset()  { return byte_offset_of(JavaThread, _stack_overflow_limit); }
   static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
   static ByteSize stack_guard_state_offset()     { return byte_offset_of(JavaThread, _stack_guard_state); }
+  static ByteSize reserved_stack_activation_offset() { return byte_offset_of(JavaThread, _reserved_stack_activation); }
   static ByteSize suspend_flags_offset()         { return byte_offset_of(JavaThread, _suspend_flags); }
 
   static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); }
--- a/hotspot/src/share/vm/runtime/thread.inline.hpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/thread.inline.hpp	Fri Dec 11 09:07:07 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,10 @@
   return _stack_guard_state == stack_guard_yellow_disabled;
 }
 
+inline bool JavaThread::stack_reserved_zone_disabled() {
+  return _stack_guard_state == stack_guard_reserved_disabled;
+}
+
 inline size_t JavaThread::stack_available(address cur_sp) {
   // This code assumes java stacks grow down
   address low_addr; // Limit on the address for deepest stack depth
@@ -141,7 +145,7 @@
   return cur_sp > low_addr ? cur_sp - low_addr : 0;
 }
 
-inline bool JavaThread::stack_yellow_zone_enabled() {
+inline bool JavaThread::stack_guards_enabled() {
 #ifdef ASSERT
   if (os::uses_stack_guard_pages()) {
     assert(_stack_guard_state != stack_guard_unused, "guard pages must be in use");
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Fri Dec 11 09:07:07 2015 -0800
@@ -396,7 +396,7 @@
   nonstatic_field(Method,                      _access_flags,                                 AccessFlags)                           \
   nonstatic_field(Method,                      _vtable_index,                                 int)                                   \
   nonstatic_field(Method,                      _intrinsic_id,                                 u2)                                    \
-  nonstatic_field(Method,                      _flags,                                        u1)                                    \
+  nonstatic_field(Method,                      _flags,                                        u2)                                    \
   nonproduct_nonstatic_field(Method,           _compiled_invocation_count,                    int)                                   \
   volatile_nonstatic_field(Method,             _code,                                         nmethod*)                              \
   nonstatic_field(Method,                      _i2i_entry,                                    address)                               \
--- a/hotspot/src/share/vm/trace/trace.xml	Fri Dec 11 13:18:10 2015 +0000
+++ b/hotspot/src/share/vm/trace/trace.xml	Fri Dec 11 09:07:07 2015 -0800
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -109,6 +109,11 @@
       <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on" relation="JAVA_MONITOR_ADDRESS"/>
     </event>
 
+    <event id="ReservedStackActivation" path="java/reserved_stack_activation" label="Reserved Stack Activation" description="Activation of Reserved Stack Area caused by stack overflow with ReservedStackAccess annotated method in call stack"
+            has_thread="true" has_stacktrace="true" is_instant="true">
+        <value type="METHOD" field="method" label="Java Method"/>
+    </event>
+
     <event id="ClassLoad" path="vm/class/load" label="Class Load"
             has_thread="true" has_stacktrace="true" is_instant="false">
       <value type="CLASS" field="loadedClass" label="Loaded Class"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java	Fri Dec 11 09:07:07 2015 -0800
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test ReservedStackTest
+ * @run main/othervm -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest
+ */
+
+/* The exclusion of java.util.concurrent.locks.AbstractOwnableSynchronizer.setExclusiveOwnerThread()
+ * from the compilable methods is required to ensure that the test will be able
+ * to trigger a StackOverflowError on the right method.
+ */
+
+
+/*
+ * Notes about this test:
+ * This test tries to reproduce a rare but nasty corruption bug that
+ * occurs when a StackOverflowError is thrown in some critical sections
+ * of the ReentrantLock implementation.
+ *
+ * Here's the critical section where a corruption could occur
+ * (from java.util.concurrent.ReentrantLock.java)
+ *
+ * final void lock() {
+ *     if (compareAndSetState(0, 1))
+ *         setExclusiveOwnerThread(Thread.currentThread());
+ *     else
+ *         acquire(1);
+ * }
+ *
+ * The corruption occurs when the compareAndSetState(0, 1)
+ * successfully updates the status of the lock but the method
+ * fails to set the owner because of a stack overflow.
+ * HotSpot checks for stack overflow on method invocations.
+ * The test must trigger a stack overflow either when
+ * Thread.currentThread() or setExclusiveOwnerThread() is
+ * invoked.
+ *
+ * The test starts with a recursive invocation loop until a
+ * first StackOverflowError is thrown, the Error is caught
+ * and a few dozen frames are exited. Now the thread has
+ * little free space on its execution stack and will try
+ * to trigger a stack overflow in the critical section.
+ * The test has a huge array of ReentrantLocks instances.
+ * The thread invokes a recursive method which, at each
+ * of its invocations, tries to acquire the next lock
+ * in the array. The execution continues until a
+ * StackOverflowError is thrown or the end of the array
+ * is reached.
+ * If no StackOverflowError has been thrown, the test
+ * is non conclusive (recommendation: increase the size
+ * of the ReentrantLock array).
+ * The status of all Reentrant locks in the array is checked,
+ * if a corruption is detected, the test failed, otherwise
+ * the test passed.
+ *
+ * To have a chance that the stack overflow occurs on one
+ * of the two targeted method invocations, the test is
+ * repeated in different threads. Each Java thread has a
+ * random size area allocated at the beginning of its
+ * stack to prevent false sharing. The test relies on this
+ * to have different stack alignments when it hits the targeted
+ * methods (the test could have been written with a native
+ * method with alloca, but using different Java threads makes
+ * the test 100% Java).
+ *
+ * One additional trick is required to ensure that the stack
+ * overflow will occur on the Thread.currentThread() getter
+ * or the setExclusiveOwnerThread() setter.
+ *
+ * Potential stack overflows are detected by stack banging,
+ * at method invocation time.
+ * In interpreted code, the stack banging performed for the
+ * lock() method goes further than the stack banging performed
+ * for the getter or the setter method, so the potential stack
+ * overflow is detected before entering the critical section.
+ * In compiled code, the getter and the setter are in-lined,
+ * so the stack banging is only performed before entering the
+ * critical section.
+ * In order to have a stack banging that goes further for the
+ * getter/setter methods than for the lock() method, the test
+ * exploits the property that interpreter frames are (much)
+ * bigger than compiled code frames. When the test is run,
+ * a compiler option disables the compilation of the
+ * setExclusiveOwnerThread() method.
+ *
+ */
+
+import java.util.concurrent.locks.ReentrantLock;
+
+public class ReservedStackTest {
+
+    private static boolean isWindows() {
+        return System.getProperty("os.name").toLowerCase().startsWith("win");
+    }
+
+    static class ReentrantLockTest {
+
+        private ReentrantLock lockArray[];
+        // Frame sizes vary a lot between interpreted code and compiled code
+        // so the lock array has to be big enough to cover all cases.
+        // If test fails with message "Not conclusive test", try to increase
+        // LOCK_ARRAY_SIZE value
+        private static final int LOCK_ARRAY_SIZE = 8192;
+        private boolean stackOverflowErrorReceived;
+        StackOverflowError soe = null;
+        private int index = -1;
+
+        public void initialize() {
+            lockArray = new ReentrantLock[LOCK_ARRAY_SIZE];
+            for (int i = 0; i < LOCK_ARRAY_SIZE; i++) {
+                lockArray[i] = new ReentrantLock();
+            }
+            stackOverflowErrorReceived = false;
+        }
+
+        public String getResult() {
+            if (!stackOverflowErrorReceived) {
+                return "ERROR: Not conclusive test: no StackOverflowError received";
+            }
+            for (int i = 0; i < LOCK_ARRAY_SIZE; i++) {
+                if (lockArray[i].isLocked()) {
+                    if (!lockArray[i].isHeldByCurrentThread()) {
+                        StringBuilder s = new StringBuilder();
+                        s.append("FAILED: ReentrantLock ");
+                        s.append(i);
+                        s.append(" looks corrupted");
+                        return s.toString();
+                    }
+                }
+            }
+            return "PASSED";
+        }
+
+        public void run() {
+            try {
+                lockAndCall(0);
+            } catch (StackOverflowError e) {
+                soe = e;
+                stackOverflowErrorReceived = true;
+            }
+        }
+
+        private void lockAndCall(int i) {
+            index = i;
+            if (i < LOCK_ARRAY_SIZE) {
+                lockArray[i].lock();
+                lockAndCall(i + 1);
+            }
+        }
+    }
+
+    static class RunWithSOEContext implements Runnable {
+
+        int counter;
+        int deframe;
+        int decounter;
+        int setupSOEFrame;
+        int testStartFrame;
+        ReentrantLockTest test;
+
+        public RunWithSOEContext(ReentrantLockTest test, int deframe) {
+            this.test = test;
+            this.deframe = deframe;
+        }
+
+        @Override
+        @jdk.internal.vm.annotation.ReservedStackAccess
+        public void run() {
+            counter = 0;
+            decounter = deframe;
+            test.initialize();
+            recursiveCall();
+            System.out.println("Framework got StackOverflowError at frame = " + counter);
+            System.out.println("Test started execution at frame = " + (counter - deframe));
+            String result = test.getResult();
+            System.out.println(result);
+            // The feature is not fully implemented on Windows platforms,
+            // corruptions are still possible
+            if (!isWindows() && !result.contains("PASSED")) {
+                System.exit(-1);
+            }
+        }
+
+        void recursiveCall() {
+            // Unused local variables to increase the frame size
+            long l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19;
+            long l20, l21, l22, l23, l24, l25, l26, l27, l28, l30, l31, l32, l33, l34, l35, l36, l37;
+            counter++;
+            try {
+                recursiveCall();
+            } catch (StackOverflowError e) {
+            }
+            decounter--;
+            if (decounter == 0) {
+                setupSOEFrame = counter;
+                testStartFrame = counter - deframe;
+                test.run();
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 1000; i++) {
+            // Each iteration has to be executed by a new thread. The test
+            // relies on the random size area pushed by the VM at the beginning
+            // of the stack of each Java thread it creates.
+            Thread thread = new Thread(new RunWithSOEContext(new ReentrantLockTest(), 256));
+            thread.start();
+            try {
+                thread.join();
+            } catch (InterruptedException ex) { }
+        }
+    }
+}