提交 a390df62 编写于 作者: M mgronlun

8038624: interpretedVFrame::expressions() must respect InterpreterOopMap for liveness

Reviewed-by: coleenp, minqi
上级 dba9b6ab
...@@ -180,7 +180,7 @@ InterpreterOopMap::~InterpreterOopMap() { ...@@ -180,7 +180,7 @@ InterpreterOopMap::~InterpreterOopMap() {
} }
} }
bool InterpreterOopMap::is_empty() { bool InterpreterOopMap::is_empty() const {
bool result = _method == NULL; bool result = _method == NULL;
assert(_method != NULL || (_bci == 0 && assert(_method != NULL || (_bci == 0 &&
(_mask_size == 0 || _mask_size == USHRT_MAX) && (_mask_size == 0 || _mask_size == USHRT_MAX) &&
...@@ -196,7 +196,7 @@ void InterpreterOopMap::initialize() { ...@@ -196,7 +196,7 @@ void InterpreterOopMap::initialize() {
for (int i = 0; i < N; i++) _bit_mask[i] = 0; for (int i = 0; i < N; i++) _bit_mask[i] = 0;
} }
void InterpreterOopMap::iterate_oop(OffsetClosure* oop_closure) { void InterpreterOopMap::iterate_oop(OffsetClosure* oop_closure) const {
int n = number_of_entries(); int n = number_of_entries();
int word_index = 0; int word_index = 0;
uintptr_t value = 0; uintptr_t value = 0;
...@@ -238,7 +238,7 @@ void InterpreterOopMap::iterate_all(OffsetClosure* oop_closure, OffsetClosure* v ...@@ -238,7 +238,7 @@ void InterpreterOopMap::iterate_all(OffsetClosure* oop_closure, OffsetClosure* v
#endif #endif
void InterpreterOopMap::print() { void InterpreterOopMap::print() const {
int n = number_of_entries(); int n = number_of_entries();
tty->print("oop map for "); tty->print("oop map for ");
method()->print_value(); method()->print_value();
...@@ -469,7 +469,7 @@ void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) { ...@@ -469,7 +469,7 @@ void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) {
} }
} }
inline unsigned int OopMapCache::hash_value_for(methodHandle method, int bci) { inline unsigned int OopMapCache::hash_value_for(methodHandle method, int bci) const {
// We use method->code_size() rather than method->identity_hash() below since // We use method->code_size() rather than method->identity_hash() below since
// the mark may not be present if a pointer to the method is already reversed. // the mark may not be present if a pointer to the method is already reversed.
return ((unsigned int) bci) return ((unsigned int) bci)
...@@ -522,7 +522,7 @@ void OopMapCache::flush_obsolete_entries() { ...@@ -522,7 +522,7 @@ void OopMapCache::flush_obsolete_entries() {
void OopMapCache::lookup(methodHandle method, void OopMapCache::lookup(methodHandle method,
int bci, int bci,
InterpreterOopMap* entry_for) { InterpreterOopMap* entry_for) const {
MutexLocker x(&_mut); MutexLocker x(&_mut);
OopMapCacheEntry* entry = NULL; OopMapCacheEntry* entry = NULL;
......
...@@ -101,32 +101,31 @@ class InterpreterOopMap: ResourceObj { ...@@ -101,32 +101,31 @@ class InterpreterOopMap: ResourceObj {
// access methods // access methods
Method* method() const { return _method; } Method* method() const { return _method; }
void set_method(Method* v) { _method = v; } void set_method(Method* v) { _method = v; }
int bci() const { return _bci; } int bci() const { return _bci; }
void set_bci(int v) { _bci = v; } void set_bci(int v) { _bci = v; }
int mask_size() const { return _mask_size; } int mask_size() const { return _mask_size; }
void set_mask_size(int v) { _mask_size = v; } void set_mask_size(int v) { _mask_size = v; }
int number_of_entries() const { return mask_size() / bits_per_entry; }
// Test bit mask size and return either the in-line bit mask or allocated // Test bit mask size and return either the in-line bit mask or allocated
// bit mask. // bit mask.
uintptr_t* bit_mask() { return (uintptr_t*)(mask_size() <= small_mask_limit ? (intptr_t)_bit_mask : _bit_mask[0]); } uintptr_t* bit_mask() const { return (uintptr_t*)(mask_size() <= small_mask_limit ? (intptr_t)_bit_mask : _bit_mask[0]); }
// return the word size of_bit_mask. mask_size() <= 4 * MAX_USHORT // return the word size of_bit_mask. mask_size() <= 4 * MAX_USHORT
size_t mask_word_size() { size_t mask_word_size() const {
return (mask_size() + BitsPerWord - 1) / BitsPerWord; return (mask_size() + BitsPerWord - 1) / BitsPerWord;
} }
uintptr_t entry_at(int offset) { int i = offset * bits_per_entry; return bit_mask()[i / BitsPerWord] >> (i % BitsPerWord); } uintptr_t entry_at(int offset) const { int i = offset * bits_per_entry; return bit_mask()[i / BitsPerWord] >> (i % BitsPerWord); }
void set_expression_stack_size(int sz) { _expression_stack_size = sz; } void set_expression_stack_size(int sz) { _expression_stack_size = sz; }
#ifdef ENABLE_ZAP_DEAD_LOCALS #ifdef ENABLE_ZAP_DEAD_LOCALS
bool is_dead(int offset) { return (entry_at(offset) & (1 << dead_bit_number)) != 0; } bool is_dead(int offset) const { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
#endif #endif
// Lookup // Lookup
bool match(methodHandle method, int bci) { return _method == method() && _bci == bci; } bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; }
bool is_empty(); bool is_empty() const;
// Initialization // Initialization
void initialize(); void initialize();
...@@ -141,12 +140,13 @@ class InterpreterOopMap: ResourceObj { ...@@ -141,12 +140,13 @@ class InterpreterOopMap: ResourceObj {
// in-line), allocate the space from a Resource area. // in-line), allocate the space from a Resource area.
void resource_copy(OopMapCacheEntry* from); void resource_copy(OopMapCacheEntry* from);
void iterate_oop(OffsetClosure* oop_closure); void iterate_oop(OffsetClosure* oop_closure) const;
void print(); void print() const;
bool is_oop (int offset) { return (entry_at(offset) & (1 << oop_bit_number )) != 0; } int number_of_entries() const { return mask_size() / bits_per_entry; }
bool is_oop (int offset) const { return (entry_at(offset) & (1 << oop_bit_number )) != 0; }
int expression_stack_size() { return _expression_stack_size; } int expression_stack_size() const { return _expression_stack_size; }
#ifdef ENABLE_ZAP_DEAD_LOCALS #ifdef ENABLE_ZAP_DEAD_LOCALS
void iterate_all(OffsetClosure* oop_closure, OffsetClosure* value_closure, OffsetClosure* dead_closure); void iterate_all(OffsetClosure* oop_closure, OffsetClosure* value_closure, OffsetClosure* dead_closure);
...@@ -161,10 +161,10 @@ class OopMapCache : public CHeapObj<mtClass> { ...@@ -161,10 +161,10 @@ class OopMapCache : public CHeapObj<mtClass> {
OopMapCacheEntry* _array; OopMapCacheEntry* _array;
unsigned int hash_value_for(methodHandle method, int bci); unsigned int hash_value_for(methodHandle method, int bci) const;
OopMapCacheEntry* entry_at(int i) const; OopMapCacheEntry* entry_at(int i) const;
Mutex _mut; mutable Mutex _mut;
void flush(); void flush();
...@@ -177,7 +177,7 @@ class OopMapCache : public CHeapObj<mtClass> { ...@@ -177,7 +177,7 @@ class OopMapCache : public CHeapObj<mtClass> {
// Returns the oopMap for (method, bci) in parameter "entry". // Returns the oopMap for (method, bci) in parameter "entry".
// Returns false if an oop map was not found. // Returns false if an oop map was not found.
void lookup(methodHandle method, int bci, InterpreterOopMap* entry); void lookup(methodHandle method, int bci, InterpreterOopMap* entry) const;
// Compute an oop map without updating the cache or grabbing any locks (for debugging) // Compute an oop map without updating the cache or grabbing any locks (for debugging)
static void compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry); static void compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry);
......
...@@ -260,65 +260,156 @@ Method* interpretedVFrame::method() const { ...@@ -260,65 +260,156 @@ Method* interpretedVFrame::method() const {
return fr().interpreter_frame_method(); return fr().interpreter_frame_method();
} }
StackValueCollection* interpretedVFrame::locals() const { static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
int length = method()->max_locals(); int index,
const intptr_t* const addr) {
assert(index >= 0 &&
index < oop_mask.number_of_entries(), "invariant");
// categorize using oop_mask
if (oop_mask.is_oop(index)) {
// reference (oop) "r"
Handle h(addr != NULL ? (*(oop*)addr) : (oop)NULL);
return new StackValue(h);
}
// value (integer) "v"
return new StackValue(addr != NULL ? *addr : 0);
}
static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) {
assert(addr != NULL, "invariant");
// Ensure to be 'inside' the expresion stack (i.e., addr >= sp for Intel).
// In case of exceptions, the expression stack is invalid and the sp
// will be reset to express this condition.
if (frame::interpreter_frame_expression_stack_direction() > 0) {
return addr <= fr.interpreter_frame_tos_address();
}
return addr >= fr.interpreter_frame_tos_address();
}
static void stack_locals(StackValueCollection* result,
int length,
const InterpreterOopMap& oop_mask,
const frame& fr) {
assert(result != NULL, "invariant");
for (int i = 0; i < length; ++i) {
const intptr_t* const addr = fr.interpreter_frame_local_at(i);
assert(addr != NULL, "invariant");
assert(addr >= fr.sp(), "must be inside the frame");
StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
assert(sv != NULL, "sanity check");
result->add(sv);
}
}
static void stack_expressions(StackValueCollection* result,
int length,
int max_locals,
const InterpreterOopMap& oop_mask,
const frame& fr) {
assert(result != NULL, "invariant");
if (method()->is_native()) { for (int i = 0; i < length; ++i) {
// If the method is native, max_locals is not telling the truth. const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i);
// maxlocals then equals the size of parameters assert(addr != NULL, "invariant");
length = method()->size_of_parameters(); if (!is_in_expression_stack(fr, addr)) {
// Need to ensure no bogus escapes.
addr = NULL;
}
StackValue* const sv = create_stack_value_from_oop_map(oop_mask,
i + max_locals,
addr);
assert(sv != NULL, "sanity check");
result->add(sv);
} }
}
StackValueCollection* result = new StackValueCollection(length); StackValueCollection* interpretedVFrame::locals() const {
return stack_data(false);
}
StackValueCollection* interpretedVFrame::expressions() const {
return stack_data(true);
}
/*
* Worker routine for fetching references and/or values
* for a particular bci in the interpretedVFrame.
*
* Returns data for either "locals" or "expressions",
* using bci relative oop_map (oop_mask) information.
*
* @param expressions bool switch controlling what data to return
(false == locals / true == expressions)
*
*/
StackValueCollection* interpretedVFrame::stack_data(bool expressions) const {
// Get oopmap describing oops and int for current bci
InterpreterOopMap oop_mask; InterpreterOopMap oop_mask;
// oopmap for current bci
if (TraceDeoptimization && Verbose) { if (TraceDeoptimization && Verbose) {
methodHandle m_h(thread(), method()); methodHandle m_h(Thread::current(), method());
OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
} else { } else {
method()->mask_for(bci(), &oop_mask); method()->mask_for(bci(), &oop_mask);
} }
// handle locals
for(int i=0; i < length; i++) {
// Find stack location
intptr_t *addr = locals_addr_at(i);
// Depending on oop/int put it in the right package const int mask_len = oop_mask.number_of_entries();
StackValue *sv;
if (oop_mask.is_oop(i)) { // If the method is native, method()->max_locals() is not telling the truth.
// oop value // For our purposes, max locals instead equals the size of parameters.
Handle h(*(oop *)addr); const int max_locals = method()->is_native() ?
sv = new StackValue(h); method()->size_of_parameters() : method()->max_locals();
} else {
// integer assert(mask_len >= max_locals, "invariant");
sv = new StackValue(*addr);
} const int length = expressions ? mask_len - max_locals : max_locals;
assert(sv != NULL, "sanity check"); assert(length >= 0, "invariant");
result->add(sv);
StackValueCollection* const result = new StackValueCollection(length);
if (0 == length) {
return result;
} }
if (expressions) {
stack_expressions(result, length, max_locals, oop_mask, fr());
} else {
stack_locals(result, length, oop_mask, fr());
}
assert(length == result->size(), "invariant");
return result; return result;
} }
void interpretedVFrame::set_locals(StackValueCollection* values) const { void interpretedVFrame::set_locals(StackValueCollection* values) const {
if (values == NULL || values->size() == 0) return; if (values == NULL || values->size() == 0) return;
int length = method()->max_locals(); // If the method is native, max_locals is not telling the truth.
if (method()->is_native()) { // maxlocals then equals the size of parameters
// If the method is native, max_locals is not telling the truth. const int max_locals = method()->is_native() ?
// maxlocals then equals the size of parameters method()->size_of_parameters() : method()->max_locals();
length = method()->size_of_parameters();
}
assert(length == values->size(), "Mismatch between actual stack format and supplied data"); assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data");
// handle locals // handle locals
for (int i = 0; i < length; i++) { for (int i = 0; i < max_locals; i++) {
// Find stack location // Find stack location
intptr_t *addr = locals_addr_at(i); intptr_t *addr = locals_addr_at(i);
// Depending on oop/int put it in the right package // Depending on oop/int put it in the right package
StackValue *sv = values->at(i); const StackValue* const sv = values->at(i);
assert(sv != NULL, "sanity check"); assert(sv != NULL, "sanity check");
if (sv->type() == T_OBJECT) { if (sv->type() == T_OBJECT) {
*(oop *) addr = (sv->get_obj())(); *(oop *) addr = (sv->get_obj())();
...@@ -328,46 +419,6 @@ void interpretedVFrame::set_locals(StackValueCollection* values) const { ...@@ -328,46 +419,6 @@ void interpretedVFrame::set_locals(StackValueCollection* values) const {
} }
} }
StackValueCollection* interpretedVFrame::expressions() const {
int length = fr().interpreter_frame_expression_stack_size();
if (method()->is_native()) {
// If the method is native, there is no expression stack
length = 0;
}
int nof_locals = method()->max_locals();
StackValueCollection* result = new StackValueCollection(length);
InterpreterOopMap oop_mask;
// Get oopmap describing oops and int for current bci
if (TraceDeoptimization && Verbose) {
methodHandle m_h(method());
OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
} else {
method()->mask_for(bci(), &oop_mask);
}
// handle expressions
for(int i=0; i < length; i++) {
// Find stack location
intptr_t *addr = fr().interpreter_frame_expression_stack_at(i);
// Depending on oop/int put it in the right package
StackValue *sv;
if (oop_mask.is_oop(i + nof_locals)) {
// oop value
Handle h(*(oop *)addr);
sv = new StackValue(h);
} else {
// integer
sv = new StackValue(*addr);
}
assert(sv != NULL, "sanity check");
result->add(sv);
}
return result;
}
// ------------- cChunk -------------- // ------------- cChunk --------------
entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
......
...@@ -186,7 +186,7 @@ class interpretedVFrame: public javaVFrame { ...@@ -186,7 +186,7 @@ class interpretedVFrame: public javaVFrame {
private: private:
static const int bcp_offset; static const int bcp_offset;
intptr_t* locals_addr_at(int offset) const; intptr_t* locals_addr_at(int offset) const;
StackValueCollection* stack_data(bool expressions) const;
// returns where the parameters starts relative to the frame pointer // returns where the parameters starts relative to the frame pointer
int start_of_parameters() const; int start_of_parameters() const;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册