Wed, 12 May 2010 03:49:52 -0700
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>
1.1 --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue May 11 15:19:19 2010 -0700 1.2 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed May 12 03:49:52 2010 -0700 1.3 @@ -37,15 +37,18 @@ 1.4 thread->reset_last_Java_frame(); \ 1.5 fixup_after_potential_safepoint() 1.6 1.7 -void CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.8 +int CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.9 JavaThread *thread = (JavaThread *) THREAD; 1.10 1.11 // Allocate and initialize our frame. 1.12 - InterpreterFrame *frame = InterpreterFrame::build(method, CHECK); 1.13 + InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0); 1.14 thread->push_zero_frame(frame); 1.15 1.16 // Execute those bytecodes! 1.17 main_loop(0, THREAD); 1.18 + 1.19 + // No deoptimized frames on the stack 1.20 + return 0; 1.21 } 1.22 1.23 void CppInterpreter::main_loop(int recurse, TRAPS) { 1.24 @@ -165,7 +168,7 @@ 1.25 stack->push(result[-i]); 1.26 } 1.27 1.28 -void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.29 +int CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.30 // Make sure method is native and not abstract 1.31 assert(method->is_native() && !method->is_abstract(), "should be"); 1.32 1.33 @@ -173,7 +176,7 @@ 1.34 ZeroStack *stack = thread->zero_stack(); 1.35 1.36 // Allocate and initialize our frame 1.37 - InterpreterFrame *frame = InterpreterFrame::build(method, CHECK); 1.38 + InterpreterFrame *frame = InterpreterFrame::build(method, CHECK_0); 1.39 thread->push_zero_frame(frame); 1.40 interpreterState istate = frame->interpreter_state(); 1.41 intptr_t *locals = istate->locals(); 1.42 @@ -430,25 +433,26 @@ 1.43 ShouldNotReachHere(); 1.44 } 1.45 } 1.46 + 1.47 + // No deoptimized frames on the stack 1.48 + return 0; 1.49 } 1.50 1.51 -void CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.52 +int CppInterpreter::accessor_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.53 JavaThread *thread = (JavaThread *) THREAD; 1.54 ZeroStack *stack = thread->zero_stack(); 1.55 intptr_t *locals = stack->sp(); 1.56 1.57 // Drop into the slow path if we need a safepoint check 1.58 if (SafepointSynchronize::do_call_back()) { 1.59 - normal_entry(method, 0, THREAD); 1.60 - return; 1.61 + return normal_entry(method, 0, THREAD); 1.62 } 1.63 1.64 // Load the object pointer and drop into the slow path 1.65 // if we have a NullPointerException 1.66 oop object = LOCALS_OBJECT(0); 1.67 if (object == NULL) { 1.68 - normal_entry(method, 0, THREAD); 1.69 - return; 1.70 + return normal_entry(method, 0, THREAD); 1.71 } 1.72 1.73 // Read the field index from the bytecode, which looks like this: 1.74 @@ -470,15 +474,14 @@ 1.75 constantPoolCacheOop cache = method->constants()->cache(); 1.76 ConstantPoolCacheEntry* entry = cache->entry_at(index); 1.77 if (!entry->is_resolved(Bytecodes::_getfield)) { 1.78 - normal_entry(method, 0, THREAD); 1.79 - return; 1.80 + return normal_entry(method, 0, THREAD); 1.81 } 1.82 1.83 // Get the result and push it onto the stack 1.84 switch (entry->flag_state()) { 1.85 case ltos: 1.86 case dtos: 1.87 - stack->overflow_check(1, CHECK); 1.88 + stack->overflow_check(1, CHECK_0); 1.89 stack->alloc(wordSize); 1.90 break; 1.91 } 1.92 @@ -558,20 +561,25 @@ 1.93 ShouldNotReachHere(); 1.94 } 1.95 } 1.96 + 1.97 + // No deoptimized frames on the stack 1.98 + return 0; 1.99 } 1.100 1.101 -void CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.102 +int CppInterpreter::empty_entry(methodOop method, intptr_t UNUSED, TRAPS) { 1.103 JavaThread *thread = (JavaThread *) THREAD; 1.104 ZeroStack *stack = thread->zero_stack(); 1.105 1.106 // Drop into the slow path if we need a safepoint check 1.107 if (SafepointSynchronize::do_call_back()) { 1.108 - normal_entry(method, 0, THREAD); 1.109 - return; 1.110 + return normal_entry(method, 0, THREAD); 1.111 } 1.112 1.113 // Pop our parameters 1.114 stack->set_sp(stack->sp() + method->size_of_parameters()); 1.115 + 1.116 + // No deoptimized frames on the stack 1.117 + return 0; 1.118 } 1.119 1.120 InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) {
2.1 --- a/src/cpu/zero/vm/cppInterpreter_zero.hpp Tue May 11 15:19:19 2010 -0700 2.2 +++ b/src/cpu/zero/vm/cppInterpreter_zero.hpp Wed May 12 03:49:52 2010 -0700 2.3 @@ -29,10 +29,10 @@ 2.4 2.5 public: 2.6 // Method entries 2.7 - static void normal_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.8 - static void native_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.9 - static void accessor_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.10 - static void empty_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.11 + static int normal_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.12 + static int native_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.13 + static int accessor_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.14 + static int empty_entry(methodOop method, intptr_t UNUSED, TRAPS); 2.15 2.16 public: 2.17 // Main loop of normal_entry
3.1 --- a/src/cpu/zero/vm/entry_zero.hpp Tue May 11 15:19:19 2010 -0700 3.2 +++ b/src/cpu/zero/vm/entry_zero.hpp Wed May 12 03:49:52 2010 -0700 3.3 @@ -1,6 +1,6 @@ 3.4 /* 3.5 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. 3.6 - * Copyright 2008, 2009 Red Hat, Inc. 3.7 + * Copyright 2008, 2009, 2010 Red Hat, Inc. 3.8 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.9 * 3.10 * This code is free software; you can redistribute it and/or modify it 3.11 @@ -41,20 +41,30 @@ 3.12 } 3.13 3.14 private: 3.15 - typedef void (*NormalEntryFunc)(methodOop method, 3.16 - intptr_t base_pc, 3.17 - TRAPS); 3.18 - typedef void (*OSREntryFunc)(methodOop method, 3.19 - address osr_buf, 3.20 - intptr_t base_pc, 3.21 - TRAPS); 3.22 + typedef int (*NormalEntryFunc)(methodOop method, 3.23 + intptr_t base_pc, 3.24 + TRAPS); 3.25 + typedef int (*OSREntryFunc)(methodOop method, 3.26 + address osr_buf, 3.27 + intptr_t base_pc, 3.28 + TRAPS); 3.29 3.30 public: 3.31 void invoke(methodOop method, TRAPS) const { 3.32 - ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD); 3.33 + maybe_deoptimize( 3.34 + ((NormalEntryFunc) entry_point())(method, (intptr_t) this, THREAD), 3.35 + THREAD); 3.36 } 3.37 void invoke_osr(methodOop method, address osr_buf, TRAPS) const { 3.38 - ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD); 3.39 + maybe_deoptimize( 3.40 + ((OSREntryFunc) entry_point())(method, osr_buf, (intptr_t) this, THREAD), 3.41 + THREAD); 3.42 + } 3.43 + 3.44 + private: 3.45 + static void maybe_deoptimize(int deoptimized_frames, TRAPS) { 3.46 + if (deoptimized_frames) 3.47 + CppInterpreter::main_loop(deoptimized_frames - 1, THREAD); 3.48 } 3.49 3.50 public: