6951784: Zero deoptimizer changes
Summary: The way Zero currently handles deoptimization can lead to methods being freed while they are still being executed.
Reviewed-by: twisti
Contributed-by: Gary Benson <gbenson@redhat.com>
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue May 11 15:19:19 2010 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed May 12 03:49:52 2010 -0700
@@ -37,15 +37,18 @@
thread->reset_last_Java_frame(); \
fixup_after_potential_safepoint()
-void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
JavaThread *thread = (JavaThread *) THREAD;
// Allocate and initialize our frame.
- InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
+ InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0);
thread->push_zero_frame(frame);
// Execute those bytecodes!
main_loop(0, THREAD);
+
+ // No deoptimized frames on the stack
+ return 0;
}
void CppInterpreter::main_loop(int recurse, TRAPS) {
@@ -165,7 +168,7 @@
stack->push(result[-i]);
}
-void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
// Make sure method is native and not abstract
assert(method->is_native() && !method->is_abstract(), "should be");
@@ -173,7 +176,7 @@
ZeroStack *stack = thread->zero_stack();
// Allocate and initialize our frame
- InterpreterFrame *frame = InterpreterFrame::build(method, CHECK);
+ InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0);
thread->push_zero_frame(frame);
interpreterState istate = frame->interpreter_state();
intptr_t *locals = istate->locals();
@@ -430,25 +433,26 @@
ShouldNotReachHere();
}
}
+
+ // No deoptimized frames on the stack
+ return 0;
}
-void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) {
JavaThread *thread = (JavaThread *) THREAD;
ZeroStack *stack = thread->zero_stack();
intptr_t *locals = stack->sp();
// Drop into the slow path if we need a safepoint check
if (SafepointSynchronize::do_call_back()) {
- normal_entry(method, 0, THREAD);
- return;
+ return normal_entry(method, 0, THREAD);
}
// Load the object pointer and drop into the slow path
// if we have a NullPointerException
oop object = LOCALS_OBJECT(0);
if (object == NULL) {
- normal_entry(method, 0, THREAD);
- return;
+ return normal_entry(method, 0, THREAD);
}
// Read the field index from the bytecode, which looks like this:
@@ -470,15 +474,14 @@
constantPoolCacheOop cache = method->constants()->cache();
ConstantPoolCacheEntry* entry = cache->entry_at(index);
if (!entry->is_resolved(Bytecodes::_getfield)) {
- normal_entry(method, 0, THREAD);
- return;
+ return normal_entry(method, 0, THREAD);
}
// Get the result and push it onto the stack
switch (entry->flag_state()) {
case ltos:
case dtos:
- stack->overflow_check(1, CHECK);
+ stack->overflow_check(1, CHECK_0);
stack->alloc(wordSize);
break;
}
@@ -558,20 +561,25 @@
ShouldNotReachHere();
}
}
+
+ // No deoptimized frames on the stack
+ return 0;
}
-void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+int CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) {
JavaThread *thread = (JavaThread *) THREAD;
ZeroStack *stack = thread->zero_stack();
// Drop into the slow path if we need a safepoint check
if (SafepointSynchronize::do_call_back()) {
- normal_entry(method, 0, THREAD);
- return;
+ return normal_entry(method, 0, THREAD);
}
// Pop our parameters
stack->set_sp(stack->sp() + method->size_of_parameters());
+
+ // No deoptimized frames on the stack
+ return 0;
}
InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) {
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Tue May 11 15:19:19 2010 -0700
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Wed May 12 03:49:52 2010 -0700
@@ -29,10 +29,10 @@
public:
// Method entries
- static void normal_entry(methodOop method, intptr_t UNUSED, TRAPS);
- static void native_entry(methodOop method, intptr_t UNUSED, TRAPS);
- static void accessor_entry(methodOop method, intptr_t UNUSED, TRAPS);
- static void empty_entry(methodOop method, intptr_t UNUSED, TRAPS);
+ static int normal_entry(methodOop method, intptr_t UNUSED, TRAPS);
+ static int native_entry(methodOop method, intptr_t UNUSED, TRAPS);
+ static int accessor_entry(methodOop method, intptr_t UNUSED, TRAPS);
+ static int empty_entry(methodOop method, intptr_t UNUSED, TRAPS);
public:
// Main loop of normal_entry
--- a/hotspot/src/cpu/zero/vm/entry_zero.hpp Tue May 11 15:19:19 2010 -0700
+++ b/hotspot/src/cpu/zero/vm/entry_zero.hpp Wed May 12 03:49:52 2010 -0700
@@ -1,6 +1,6 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,20 +41,30 @@
}
private:
- typedef void (*NormalEntryFunc)(methodOop method,
- intptr_t base_pc,
- TRAPS);
- typedef void (*OSREntryFunc)(methodOop method,
- address osr_buf,
- intptr_t base_pc,
- TRAPS);
+ typedef int (*NormalEntryFunc)(methodOop method,
+ intptr_t base_pc,
+ TRAPS);
+ typedef int (*OSREntryFunc)(methodOop method,
+ address osr_buf,
+ intptr_t base_pc,
+ TRAPS);
public:
void invoke(methodOop method, TRAPS) const {
- ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD);
+ maybe_deoptimize(
+ ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD),
+ THREAD);
}
void invoke_osr(methodOop method, address osr_buf, TRAPS) const {
- ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD);
+ maybe_deoptimize(
+ ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD),
+ THREAD);
+ }
+
+ private:
+ static void maybe_deoptimize(int deoptimized_frames, TRAPS) {
+ if (deoptimized_frames)
+ CppInterpreter::main_loop(deoptimized_frames - 1, THREAD);
}
public: