提交 e94f7545 编写于 作者: T twisti

6941224: Improved stack overflow handling for Zero

Summary: Adding stack overflow checking to Shark brought to light a bunch of deficiencies in Zero's stack overflow code.
Reviewed-by: twisti
Contributed-by: NGary Benson <gbenson@redhat.com>
上级 4834adc5
...@@ -39,21 +39,9 @@ ...@@ -39,21 +39,9 @@
void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) { void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
JavaThread *thread = (JavaThread *) THREAD; JavaThread *thread = (JavaThread *) THREAD;
ZeroStack *stack = thread->zero_stack();
// Adjust the caller's stack frame to accomodate any additional
// local variables we have contiguously with our parameters.
int extra_locals = method->max_locals() - method->size_of_parameters();
if (extra_locals > 0) {
if (extra_locals > stack->available_words()) {
Unimplemented();
}
for (int i = 0; i < extra_locals; i++)
stack->push(0);
}
// Allocate and initialize our frame. // Allocate and initialize our frame.
InterpreterFrame *frame = InterpreterFrame::build(stack, method, thread); InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
thread->push_zero_frame(frame); thread->push_zero_frame(frame);
// Execute those bytecodes! // Execute those bytecodes!
...@@ -76,12 +64,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { ...@@ -76,12 +64,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
intptr_t *result = NULL; intptr_t *result = NULL;
int result_slots = 0; int result_slots = 0;
// Check we're not about to run out of stack
if (stack_overflow_imminent(thread)) {
CALL_VM_NOCHECK(InterpreterRuntime::throw_StackOverflowError(thread));
goto unwind_and_return;
}
while (true) { while (true) {
// We can set up the frame anchor with everything we want at // We can set up the frame anchor with everything we want at
// this point as we are thread_in_Java and no safepoints can // this point as we are thread_in_Java and no safepoints can
...@@ -123,9 +105,9 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { ...@@ -123,9 +105,9 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
int monitor_words = frame::interpreter_frame_monitor_size(); int monitor_words = frame::interpreter_frame_monitor_size();
// Allocate the space // Allocate the space
if (monitor_words > stack->available_words()) { stack->overflow_check(monitor_words, THREAD);
Unimplemented(); if (HAS_PENDING_EXCEPTION)
} break;
stack->alloc(monitor_words * wordSize); stack->alloc(monitor_words * wordSize);
// Move the expression stack contents // Move the expression stack contents
...@@ -172,8 +154,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { ...@@ -172,8 +154,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
} }
} }
unwind_and_return:
// Unwind the current frame // Unwind the current frame
thread->pop_zero_frame(); thread->pop_zero_frame();
...@@ -193,17 +173,11 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { ...@@ -193,17 +173,11 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
ZeroStack *stack = thread->zero_stack(); ZeroStack *stack = thread->zero_stack();
// Allocate and initialize our frame // Allocate and initialize our frame
InterpreterFrame *frame = InterpreterFrame::build(stack, method, thread); InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
thread->push_zero_frame(frame); thread->push_zero_frame(frame);
interpreterState istate = frame->interpreter_state(); interpreterState istate = frame->interpreter_state();
intptr_t *locals = istate->locals(); intptr_t *locals = istate->locals();
// Check we're not about to run out of stack
if (stack_overflow_imminent(thread)) {
CALL_VM_NOCHECK(InterpreterRuntime::throw_StackOverflowError(thread));
goto unwind_and_return;
}
// Update the invocation counter // Update the invocation counter
if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) { if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) {
InvocationCounter *counter = method->invocation_counter(); InvocationCounter *counter = method->invocation_counter();
...@@ -264,9 +238,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { ...@@ -264,9 +238,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
assert(function != NULL, "should be set if signature handler is"); assert(function != NULL, "should be set if signature handler is");
// Build the argument list // Build the argument list
if (handler->argument_count() * 2 > stack->available_words()) { stack->overflow_check(handler->argument_count() * 2, THREAD);
Unimplemented(); if (HAS_PENDING_EXCEPTION)
} goto unlock_unwind_and_return;
void **arguments; void **arguments;
void *mirror; { void *mirror; {
arguments = arguments =
...@@ -503,9 +478,7 @@ void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) { ...@@ -503,9 +478,7 @@ void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
switch (entry->flag_state()) { switch (entry->flag_state()) {
case ltos: case ltos:
case dtos: case dtos:
if (stack->available_words() < 1) { stack->overflow_check(1, CHECK);
Unimplemented();
}
stack->alloc(wordSize); stack->alloc(wordSize);
break; break;
} }
...@@ -601,39 +574,30 @@ void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) { ...@@ -601,39 +574,30 @@ void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) {
stack->set_sp(stack->sp() + method->size_of_parameters()); stack->set_sp(stack->sp() + method->size_of_parameters());
} }
bool CppInterpreter::stack_overflow_imminent(JavaThread *thread) { InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) {
// How is the ABI stack? JavaThread *thread = (JavaThread *) THREAD;
address stack_top = thread->stack_base() - thread->stack_size(); ZeroStack *stack = thread->zero_stack();
int free_stack = os::current_stack_pointer() - stack_top;
if (free_stack < StackShadowPages * os::vm_page_size()) {
return true;
}
// How is the Zero stack?
// Throwing a StackOverflowError involves a VM call, which means
// we need a frame on the stack. We should be checking here to
// ensure that methods we call have enough room to install the
// largest possible frame, but that's more than twice the size
// of the entire Zero stack we get by default, so we just check
// we have *some* space instead...
free_stack = thread->zero_stack()->available_words() * wordSize;
if (free_stack < StackShadowPages * os::vm_page_size()) {
return true;
}
return false;
}
InterpreterFrame *InterpreterFrame::build(ZeroStack* stack, // Calculate the size of the frame we'll build, including
const methodOop method, // any adjustments to the caller's frame that we'll make.
JavaThread* thread) { int extra_locals = 0;
int monitor_words = int monitor_words = 0;
method->is_synchronized() ? frame::interpreter_frame_monitor_size() : 0; int stack_words = 0;
int stack_words = method->is_native() ? 0 : method->max_stack();
if (header_words + monitor_words + stack_words > stack->available_words()) { if (!method->is_native()) {
Unimplemented(); extra_locals = method->max_locals() - method->size_of_parameters();
stack_words = method->max_stack();
} }
if (method->is_synchronized()) {
monitor_words = frame::interpreter_frame_monitor_size();
}
stack->overflow_check(
extra_locals + header_words + monitor_words + stack_words, CHECK_NULL);
// Adjust the caller's stack frame to accomodate any additional
// local variables we have contiguously with our parameters.
for (int i = 0; i < extra_locals; i++)
stack->push(0);
intptr_t *locals; intptr_t *locals;
if (method->is_native()) if (method->is_native())
...@@ -812,14 +776,13 @@ InterpreterGenerator::InterpreterGenerator(StubQueue* code) ...@@ -812,14 +776,13 @@ InterpreterGenerator::InterpreterGenerator(StubQueue* code)
// Deoptimization helpers // Deoptimization helpers
InterpreterFrame *InterpreterFrame::build(ZeroStack* stack, int size) { InterpreterFrame *InterpreterFrame::build(int size, TRAPS) {
ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack();
int size_in_words = size >> LogBytesPerWord; int size_in_words = size >> LogBytesPerWord;
assert(size_in_words * wordSize == size, "unaligned"); assert(size_in_words * wordSize == size, "unaligned");
assert(size_in_words >= header_words, "too small"); assert(size_in_words >= header_words, "too small");
stack->overflow_check(size_in_words, CHECK_NULL);
if (size_in_words > stack->available_words()) {
Unimplemented();
}
stack->push(0); // next_frame, filled in later stack->push(0); // next_frame, filled in later
intptr_t *fp = stack->sp(); intptr_t *fp = stack->sp();
......
...@@ -38,10 +38,6 @@ ...@@ -38,10 +38,6 @@
// Main loop of normal_entry // Main loop of normal_entry
static void main_loop(int recurse, TRAPS); static void main_loop(int recurse, TRAPS);
private:
// Stack overflow checks
static bool stack_overflow_imminent(JavaThread *thread);
private: private:
// Fast result type determination // Fast result type determination
static BasicType result_type_of(methodOop method); static BasicType result_type_of(methodOop method);
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2008 Red Hat, Inc. * Copyright 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,10 +47,10 @@ class EntryFrame : public ZeroFrame { ...@@ -47,10 +47,10 @@ class EntryFrame : public ZeroFrame {
}; };
public: public:
static EntryFrame *build(ZeroStack* stack, static EntryFrame *build(const intptr_t* parameters,
const intptr_t* parameters,
int parameter_words, int parameter_words,
JavaCallWrapper* call_wrapper); JavaCallWrapper* call_wrapper,
TRAPS);
public: public:
JavaCallWrapper *call_wrapper() const { JavaCallWrapper *call_wrapper() const {
return (JavaCallWrapper *) value_of_word(call_wrapper_off); return (JavaCallWrapper *) value_of_word(call_wrapper_off);
......
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2008 Red Hat, Inc. * Copyright 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -42,7 +42,7 @@ class FakeStubFrame : public ZeroFrame { ...@@ -42,7 +42,7 @@ class FakeStubFrame : public ZeroFrame {
}; };
public: public:
static FakeStubFrame *build(ZeroStack* stack); static FakeStubFrame *build(TRAPS);
public: public:
void identify_word(int frame_index, void identify_word(int frame_index,
......
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2008 Red Hat, Inc. * Copyright 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -55,10 +55,8 @@ class InterpreterFrame : public ZeroFrame { ...@@ -55,10 +55,8 @@ class InterpreterFrame : public ZeroFrame {
}; };
public: public:
static InterpreterFrame *build(ZeroStack* stack, static InterpreterFrame *build(const methodOop method, TRAPS);
const methodOop method, static InterpreterFrame *build(int size, TRAPS);
JavaThread* thread);
static InterpreterFrame *build(ZeroStack* stack, int size);
public: public:
interpreterState interpreter_state() const { interpreterState interpreter_state() const {
......
/* /*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2007, 2008 Red Hat, Inc. * Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -140,9 +140,8 @@ IRT_ENTRY(address, ...@@ -140,9 +140,8 @@ IRT_ENTRY(address,
int required_words = int required_words =
(align_size_up(sizeof(ffi_cif), wordSize) >> LogBytesPerWord) + (align_size_up(sizeof(ffi_cif), wordSize) >> LogBytesPerWord) +
(method->is_static() ? 2 : 1) + method->size_of_parameters() + 1; (method->is_static() ? 2 : 1) + method->size_of_parameters() + 1;
if (required_words > stack->available_words()) {
Unimplemented(); stack->overflow_check(required_words, CHECK_NULL);
}
intptr_t *buf = (intptr_t *) stack->alloc(required_words * wordSize); intptr_t *buf = (intptr_t *) stack->alloc(required_words * wordSize);
SlowSignatureHandlerGenerator sshg(methodHandle(thread, method), buf); SlowSignatureHandlerGenerator sshg(methodHandle(thread, method), buf);
......
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2008, 2009 Red Hat, Inc. * Copyright 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,9 +29,14 @@ class ZeroStack { ...@@ -29,9 +29,14 @@ class ZeroStack {
intptr_t *_top; // the word past the end of the stack intptr_t *_top; // the word past the end of the stack
intptr_t *_sp; // the top word on the stack intptr_t *_sp; // the top word on the stack
private:
int _shadow_pages_size; // how much ABI stack must we keep free?
public: public:
ZeroStack() ZeroStack()
: _base(NULL), _top(NULL), _sp(NULL) {} : _base(NULL), _top(NULL), _sp(NULL) {
_shadow_pages_size = StackShadowPages * os::vm_page_size();
}
bool needs_setup() const { bool needs_setup() const {
return _base == NULL; return _base == NULL;
...@@ -81,6 +86,14 @@ class ZeroStack { ...@@ -81,6 +86,14 @@ class ZeroStack {
return _sp -= count; return _sp -= count;
} }
int shadow_pages_size() const {
return _shadow_pages_size;
}
public:
void overflow_check(int required_words, TRAPS);
static void handle_overflow(TRAPS);
public: public:
static ByteSize base_offset() { static ByteSize base_offset() {
return byte_offset_of(ZeroStack, _base); return byte_offset_of(ZeroStack, _base);
......
/* /*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2007, 2008 Red Hat, Inc. * Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -60,37 +60,42 @@ class StubGenerator: public StubCodeGenerator { ...@@ -60,37 +60,42 @@ class StubGenerator: public StubCodeGenerator {
} }
// Allocate and initialize our frame // Allocate and initialize our frame
thread->push_zero_frame( EntryFrame *frame =
EntryFrame::build(stack, parameters, parameter_words, call_wrapper)); EntryFrame::build(parameters, parameter_words, call_wrapper, THREAD);
// Make the call
Interpreter::invoke_method(method, entry_point, THREAD);
// Store result depending on type
if (!HAS_PENDING_EXCEPTION) { if (!HAS_PENDING_EXCEPTION) {
switch (result_type) { // Push the frame
case T_INT: thread->push_zero_frame(frame);
*(jint *) result = *(jint *) stack->sp();
break; // Make the call
case T_LONG: Interpreter::invoke_method(method, entry_point, THREAD);
*(jlong *) result = *(jlong *) stack->sp();
break; // Store the result
case T_FLOAT: if (!HAS_PENDING_EXCEPTION) {
*(jfloat *) result = *(jfloat *) stack->sp(); switch (result_type) {
break; case T_INT:
case T_DOUBLE: *(jint *) result = *(jint *) stack->sp();
*(jdouble *) result = *(jdouble *) stack->sp(); break;
break; case T_LONG:
case T_OBJECT: *(jlong *) result = *(jlong *) stack->sp();
*(oop *) result = *(oop *) stack->sp(); break;
break; case T_FLOAT:
default: *(jfloat *) result = *(jfloat *) stack->sp();
ShouldNotReachHere(); break;
case T_DOUBLE:
*(jdouble *) result = *(jdouble *) stack->sp();
break;
case T_OBJECT:
*(oop *) result = *(oop *) stack->sp();
break;
default:
ShouldNotReachHere();
}
} }
}
// Unwind our frame // Unwind the frame
thread->pop_zero_frame(); thread->pop_zero_frame();
}
// Tear down the stack if necessary // Tear down the stack if necessary
if (stack_needs_teardown) if (stack_needs_teardown)
...@@ -226,13 +231,13 @@ void StubGenerator_generate(CodeBuffer* code, bool all) { ...@@ -226,13 +231,13 @@ void StubGenerator_generate(CodeBuffer* code, bool all) {
StubGenerator g(code, all); StubGenerator g(code, all);
} }
EntryFrame *EntryFrame::build(ZeroStack* stack, EntryFrame *EntryFrame::build(const intptr_t* parameters,
const intptr_t* parameters,
int parameter_words, int parameter_words,
JavaCallWrapper* call_wrapper) { JavaCallWrapper* call_wrapper,
if (header_words + parameter_words > stack->available_words()) { TRAPS) {
Unimplemented();
} ZeroStack *stack = ((JavaThread *) THREAD)->zero_stack();
stack->overflow_check(header_words + parameter_words, CHECK_NULL);
stack->push(0); // next_frame, filled in later stack->push(0); // next_frame, filled in later
intptr_t *fp = stack->sp(); intptr_t *fp = stack->sp();
......
/* /*
* Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2007, 2008, 2009 Red Hat, Inc. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -68,12 +68,13 @@ ...@@ -68,12 +68,13 @@
public: public:
void set_last_Java_frame() { void set_last_Java_frame() {
JavaFrameAnchor *jfa = frame_anchor(); set_last_Java_frame(top_zero_frame());
jfa->set_last_Java_sp((intptr_t *) top_zero_frame());
} }
void reset_last_Java_frame() { void reset_last_Java_frame() {
JavaFrameAnchor *jfa = frame_anchor(); set_last_Java_frame(NULL);
jfa->set_last_Java_sp(NULL); }
void set_last_Java_frame(ZeroFrame* frame) {
frame_anchor()->set_last_Java_sp((intptr_t *) frame);
} }
private: private:
......
// //
// Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. // Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
// Copyright 2009 Red Hat, Inc. // Copyright 2009, 2010 Red Hat, Inc.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// //
// This code is free software; you can redistribute it and/or modify it // This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
// NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps! // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
cppInterpreter_<arch>.cpp stack_<arch>.inline.hpp
entryFrame_<arch>.hpp javaCalls.hpp entryFrame_<arch>.hpp javaCalls.hpp
entryFrame_<arch>.hpp stack_<arch>.hpp entryFrame_<arch>.hpp stack_<arch>.hpp
...@@ -47,9 +49,19 @@ interpreterFrame_<arch>.hpp methodOop.hpp ...@@ -47,9 +49,19 @@ interpreterFrame_<arch>.hpp methodOop.hpp
interpreterFrame_<arch>.hpp stack_<arch>.hpp interpreterFrame_<arch>.hpp stack_<arch>.hpp
interpreterFrame_<arch>.hpp thread.hpp interpreterFrame_<arch>.hpp thread.hpp
interpreterRT_<arch>.cpp stack_<arch>.inline.hpp
sharkFrame_<arch>.hpp methodOop.hpp sharkFrame_<arch>.hpp methodOop.hpp
sharkFrame_<arch>.hpp stack_<arch>.hpp sharkFrame_<arch>.hpp stack_<arch>.hpp
stack_<arch>.hpp sizes.hpp stack_<arch>.hpp sizes.hpp
stack_<arch>.inline.hpp stack_<arch>.hpp
stack_<arch>.inline.hpp thread.hpp
stack_<arch>.cpp interpreterRuntime.hpp
stack_<arch>.cpp stack_<arch>.hpp
stubGenerator_<arch>.cpp stack_<arch>.inline.hpp
thread.hpp stack_<arch>.hpp thread.hpp stack_<arch>.hpp
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册