# HG changeset patch # User goetz # Date 1463145606 -7200 # Node ID 69ced2325f58a79218c557e6fae7ff31d0d687a6 # Parent 2b65f4db449efcc10382f6aaf4a118a25ed40c6c 8156922: [ppc] Implement template interpreter stack overflow checks as on x86/sparc. Reviewed-by: dlong, dholmes, simonis, coleenp diff -r 2b65f4db449e -r 69ced2325f58 hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Wed Jun 01 11:14:58 2016 -0400 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp Fri May 13 15:20:06 2016 +0200 @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015 SAP SE. All rights reserved. + * Copyright (c) 2015, 2016 SAP SE. 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 @@ -562,10 +562,16 @@ return NULL; } -// Actually we should never reach here since we do stack overflow checks before pushing any frame. address TemplateInterpreterGenerator::generate_StackOverflowError_handler() { address entry = __ pc(); - __ unimplemented("generate_StackOverflowError_handler"); + + // Expression stack must be empty before entering the VM if an + // exception happened. + __ empty_expression_stack(); + // Throw exception. + __ call_VM(noreg, + CAST_FROM_FN_PTR(address, + InterpreterRuntime::throw_StackOverflowError)); return entry; } @@ -944,7 +950,7 @@ // The top most frame needs an abi space of 112 bytes. This space is needed, // since we call to c. The c function may spill their arguments to the caller // frame. When we call to java, we don't need these spill slots. In order to save -// space on the stack, we resize the caller. However, java local reside in +// space on the stack, we resize the caller. However, java locals reside in // the caller frame and the frame has to be increased. The frame_size for the // current frame was calculated based on max_stack as size for the expression // stack. At the call, just a part of the expression stack might be used. @@ -1007,7 +1013,7 @@ // parent_frame_resize = (locals-parameters) - (ESP-SP-ABI48) Rounded to frame alignment size. // Enlarge by locals-parameters (not in case of native_call), shrink by ESP-SP-ABI48. - { + if (!native_call) { // -------------------------------------------------------------------------- // Stack overflow check @@ -1047,7 +1053,7 @@ __ addi(R26_monitor, R1_SP, - frame::ijava_state_size); __ addi(R15_esp, R26_monitor, - Interpreter::stackElementSize); - // Get mirror and store it in the frame as GC root for this Method* + // Get mirror and store it in the frame as GC root for this Method*. __ load_mirror(R12_scratch2, R19_method); // Store values. @@ -1133,6 +1139,29 @@ return entry; } +void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { + // Quick & dirty stack overflow checking: bang the stack & handle trap. + // Note that we do the banging after the frame is setup, since the exception + // handling code expects to find a valid interpreter frame on the stack. + // Doing the banging earlier fails if the caller frame is not an interpreter + // frame. + // (Also, the exception throwing code expects to unlock any synchronized + // method receiever, so do the banging after locking the receiver.) + + // Bang each page in the shadow zone. We can't assume it's been done for + // an interpreter frame with greater than a page of locals, so each page + // needs to be checked. Only true for non-native. + if (UseStackBanging) { + const int page_size = os::vm_page_size(); + const int n_shadow_pages = ((int)JavaThread::stack_shadow_zone_size()) / page_size; + const int start_page = native_call ? n_shadow_pages : 1; + BLOCK_COMMENT("bang_stack_shadow_pages:"); + for (int pages = start_page; pages <= n_shadow_pages; pages++) { + __ bang_stack_with_offset(pages*page_size); + } + } +} + // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the // native method than the typical interpreter frame setup. @@ -1156,7 +1185,7 @@ // This is not a full-blown interpreter frame, but in particular, the // following registers are valid after this: // - R19_method - // - R18_local (points to start of argumuments to native function) + // - R18_local (points to start of arguments to native function) // // abstract stack (grows up) // [ IJava (caller of JNI callee) ] <-- ASP @@ -1207,6 +1236,11 @@ generate_counter_incr(&invocation_counter_overflow, NULL, NULL); BIND(continue_after_compile); + } + + bang_stack_shadow_pages(true); + + if (inc_counter) { // Reset the _do_not_unlock_if_synchronized flag. if (synchronized) { __ li(R0, 0); @@ -1595,6 +1629,7 @@ Register Rsize_of_parameters = R4_ARG2, // Written by generate_fixed_frame. Rsize_of_locals = R5_ARG3; // Written by generate_fixed_frame. + // Does also a stack check to assure this frame fits on the stack. generate_fixed_frame(false, Rsize_of_parameters, Rsize_of_locals); // -------------------------------------------------------------------------- @@ -1651,7 +1686,11 @@ } __ bind(profile_method_continue); + } + bang_stack_shadow_pages(false); + + if (inc_counter || ProfileInterpreter) { // Reset the _do_not_unlock_if_synchronized flag. if (synchronized) { __ li(R0, 0); diff -r 2b65f4db449e -r 69ced2325f58 hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Wed Jun 01 11:14:58 2016 -0400 +++ b/hotspot/src/share/vm/runtime/os.cpp Fri May 13 15:20:06 2016 +0200 @@ -1336,12 +1336,10 @@ const int framesize_in_bytes = Interpreter::size_top_interpreter_activation(method()) * wordSize; - assert((thread->stack_base() - thread->stack_size()) + - (JavaThread::stack_guard_zone_size() + - JavaThread::stack_shadow_zone_size() + framesize_in_bytes) == - ((JavaThread*)thread)->stack_overflow_limit() + framesize_in_bytes, "sanity"); + address limit = ((JavaThread*)thread)->stack_end() + + (JavaThread::stack_guard_zone_size() + JavaThread::stack_shadow_zone_size()); - return (sp > ((JavaThread*)thread)->stack_overflow_limit() + framesize_in_bytes); + return sp > (limit + framesize_in_bytes); } size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) { diff -r 2b65f4db449e -r 69ced2325f58 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Wed Jun 01 11:14:58 2016 -0400 +++ b/hotspot/src/share/vm/runtime/thread.hpp Fri May 13 15:20:06 2016 +0200 @@ -1371,10 +1371,10 @@ // | reserved pages | // | | // -- <-- stack_reserved_zone_base() --- --- - // /|\ shadow + // /|\ shadow <-- stack_overflow_limit() (somewhere in here) // | zone // \|/ size - // some untouched memory --- <-- stack_overflow_limit() + // some untouched memory --- // // // -- @@ -1522,9 +1522,8 @@ address stack_overflow_limit() { return _stack_overflow_limit; } void set_stack_overflow_limit() { - _stack_overflow_limit = stack_end() + - (JavaThread::stack_guard_zone_size() + - JavaThread::stack_shadow_zone_size()); + _stack_overflow_limit = + stack_end() + MAX2(JavaThread::stack_guard_zone_size(), JavaThread::stack_shadow_zone_size()); } // Misc. accessors/mutators