8230199: consolidate signature parsing code in HotSpot sources

Add a new Signature class to support basic signature queries and enhance SignatureStream class to parse field signatures in addition to methods.

Co-authored-by: John Rose <john.r.rose@oracle.com>
Reviewed-by: coleenp, dholmes, fparain, hseigel
This commit is contained in:
Lois Foltan 2020-02-06 14:29:57 +00:00
parent 2ede36b3a3
commit d19a396e96
57 changed files with 1394 additions and 1498 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -1333,28 +1333,16 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Arrays are passed as int, elem* pair // Arrays are passed as int, elem* pair
out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_INT;
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[i] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[i] = T_BYTE; break;
case 'C': in_elem_bt[i] = T_CHAR; break;
case 'D': in_elem_bt[i] = T_DOUBLE; break;
case 'F': in_elem_bt[i] = T_FLOAT; break;
case 'I': in_elem_bt[i] = T_INT; break;
case 'J': in_elem_bt[i] = T_LONG; break;
case 'S': in_elem_bt[i] = T_SHORT; break;
case 'Z': in_elem_bt[i] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
out_sig_bt[argc++] = in_sig_bt[i]; out_sig_bt[argc++] = in_sig_bt[i];
in_elem_bt[i] = T_VOID; in_elem_bt[i] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -1934,27 +1934,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
for (int i = 0; i < total_in_args ; i++, o++) { for (int i = 0; i < total_in_args ; i++, o++) {
if (in_sig_bt[i] == T_ARRAY) { if (in_sig_bt[i] == T_ARRAY) {
// Arrays are passed as int, elem* pair // Arrays are passed as int, elem* pair
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[o] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[o] = T_BYTE; break;
case 'C': in_elem_bt[o] = T_CHAR; break;
case 'D': in_elem_bt[o] = T_DOUBLE; break;
case 'F': in_elem_bt[o] = T_FLOAT; break;
case 'I': in_elem_bt[o] = T_INT; break;
case 'J': in_elem_bt[o] = T_LONG; break;
case 'S': in_elem_bt[o] = T_SHORT; break;
case 'Z': in_elem_bt[o] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
in_elem_bt[o] = T_VOID; in_elem_bt[o] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2019, SAP SE. All rights reserved. * Copyright (c) 2016, 2019, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -1626,27 +1626,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
for (int i = 0; i < total_in_args; i++, o++) { for (int i = 0; i < total_in_args; i++, o++) {
if (in_sig_bt[i] == T_ARRAY) { if (in_sig_bt[i] == T_ARRAY) {
// Arrays are passed as tuples (int, elem*). // Arrays are passed as tuples (int, elem*).
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[o] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[o] = T_BYTE; break;
case 'C': in_elem_bt[o] = T_CHAR; break;
case 'D': in_elem_bt[o] = T_DOUBLE; break;
case 'F': in_elem_bt[o] = T_FLOAT; break;
case 'I': in_elem_bt[o] = T_INT; break;
case 'J': in_elem_bt[o] = T_LONG; break;
case 'S': in_elem_bt[o] = T_SHORT; break;
case 'Z': in_elem_bt[o] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
in_elem_bt[o] = T_VOID; in_elem_bt[o] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -1907,28 +1907,16 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Arrays are passed as int, elem* pair // Arrays are passed as int, elem* pair
out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_INT;
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[i] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[i] = T_BYTE; break;
case 'C': in_elem_bt[i] = T_CHAR; break;
case 'D': in_elem_bt[i] = T_DOUBLE; break;
case 'F': in_elem_bt[i] = T_FLOAT; break;
case 'I': in_elem_bt[i] = T_INT; break;
case 'J': in_elem_bt[i] = T_LONG; break;
case 'S': in_elem_bt[i] = T_SHORT; break;
case 'Z': in_elem_bt[i] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
out_sig_bt[argc++] = in_sig_bt[i]; out_sig_bt[argc++] = in_sig_bt[i];
in_elem_bt[i] = T_VOID; in_elem_bt[i] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -1697,28 +1697,16 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Arrays are passed as int, elem* pair // Arrays are passed as int, elem* pair
out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_INT;
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[i] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[i] = T_BYTE; break;
case 'C': in_elem_bt[i] = T_CHAR; break;
case 'D': in_elem_bt[i] = T_DOUBLE; break;
case 'F': in_elem_bt[i] = T_FLOAT; break;
case 'I': in_elem_bt[i] = T_INT; break;
case 'J': in_elem_bt[i] = T_LONG; break;
case 'S': in_elem_bt[i] = T_SHORT; break;
case 'Z': in_elem_bt[i] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
out_sig_bt[argc++] = in_sig_bt[i]; out_sig_bt[argc++] = in_sig_bt[i];
in_elem_bt[i] = T_VOID; in_elem_bt[i] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -2002,28 +2002,16 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Arrays are passed as int, elem* pair // Arrays are passed as int, elem* pair
out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_INT;
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
Symbol* atype = ss.as_symbol(); ss.skip_array_prefix(1); // skip one '['
const char* at = atype->as_C_string(); assert(ss.is_primitive(), "primitive type expected");
if (strlen(at) == 2) { in_elem_bt[i] = ss.type();
assert(at[0] == '[', "must be");
switch (at[1]) {
case 'B': in_elem_bt[i] = T_BYTE; break;
case 'C': in_elem_bt[i] = T_CHAR; break;
case 'D': in_elem_bt[i] = T_DOUBLE; break;
case 'F': in_elem_bt[i] = T_FLOAT; break;
case 'I': in_elem_bt[i] = T_INT; break;
case 'J': in_elem_bt[i] = T_LONG; break;
case 'S': in_elem_bt[i] = T_SHORT; break;
case 'Z': in_elem_bt[i] = T_BOOLEAN; break;
default: ShouldNotReachHere();
}
}
} else { } else {
out_sig_bt[argc++] = in_sig_bt[i]; out_sig_bt[argc++] = in_sig_bt[i];
in_elem_bt[i] = T_VOID; in_elem_bt[i] = T_VOID;
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type() ||
in_sig_bt[i] == T_ARRAY, "must match");
ss.next(); ss.next();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -265,8 +265,8 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
GlobalValueNumbering* _gvn; GlobalValueNumbering* _gvn;
BlockList _loop_blocks; BlockList _loop_blocks;
bool _too_complicated_loop; bool _too_complicated_loop;
bool _has_field_store[T_ARRAY + 1]; bool _has_field_store[T_VOID];
bool _has_indexed_store[T_ARRAY + 1]; bool _has_indexed_store[T_VOID];
// simplified access to methods of GlobalValueNumbering // simplified access to methods of GlobalValueNumbering
ValueMap* current_map() { return _gvn->current_map(); } ValueMap* current_map() { return _gvn->current_map(); }
@ -276,12 +276,12 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
void kill_memory() { _too_complicated_loop = true; } void kill_memory() { _too_complicated_loop = true; }
void kill_field(ciField* field, bool all_offsets) { void kill_field(ciField* field, bool all_offsets) {
current_map()->kill_field(field, all_offsets); current_map()->kill_field(field, all_offsets);
assert(field->type()->basic_type() >= 0 && field->type()->basic_type() <= T_ARRAY, "Invalid type"); assert(field->type()->basic_type() >= 0 && field->type()->basic_type() < T_VOID, "Invalid type");
_has_field_store[field->type()->basic_type()] = true; _has_field_store[field->type()->basic_type()] = true;
} }
void kill_array(ValueType* type) { void kill_array(ValueType* type) {
current_map()->kill_array(type); current_map()->kill_array(type);
BasicType basic_type = as_BasicType(type); assert(basic_type >= 0 && basic_type <= T_ARRAY, "Invalid type"); BasicType basic_type = as_BasicType(type); assert(basic_type >= 0 && basic_type < T_VOID, "Invalid type");
_has_indexed_store[basic_type] = true; _has_indexed_store[basic_type] = true;
} }
@ -291,19 +291,19 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
, _loop_blocks(ValueMapMaxLoopSize) , _loop_blocks(ValueMapMaxLoopSize)
, _too_complicated_loop(false) , _too_complicated_loop(false)
{ {
for (int i=0; i<= T_ARRAY; i++){ for (int i = 0; i < T_VOID; i++) {
_has_field_store[i] = false; _has_field_store[i] = false;
_has_indexed_store[i] = false; _has_indexed_store[i] = false;
} }
} }
bool has_field_store(BasicType type) { bool has_field_store(BasicType type) {
assert(type >= 0 && type <= T_ARRAY, "Invalid type"); assert(type >= 0 && type < T_VOID, "Invalid type");
return _has_field_store[type]; return _has_field_store[type];
} }
bool has_indexed_store(BasicType type) { bool has_indexed_store(BasicType type) {
assert(type >= 0 && type <= T_ARRAY, "Invalid type"); assert(type >= 0 && type < T_VOID, "Invalid type");
return _has_indexed_store[type]; return _has_indexed_store[type];
} }

View file

@ -413,12 +413,10 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
// Now we need to check the SystemDictionary // Now we need to check the SystemDictionary
Symbol* sym = name->get_symbol(); Symbol* sym = name->get_symbol();
if (sym->char_at(0) == JVM_SIGNATURE_CLASS && if (Signature::has_envelope(sym)) {
sym->char_at(sym->utf8_length()-1) == JVM_SIGNATURE_ENDCLASS) {
// This is a name from a signature. Strip off the trimmings. // This is a name from a signature. Strip off the trimmings.
// Call recursive to keep scope of strippedsym. // Call recursive to keep scope of strippedsym.
TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1, TempNewSymbol strippedsym = Signature::strip_envelope(sym);
sym->utf8_length()-2);
ciSymbol* strippedname = get_symbol(strippedsym); ciSymbol* strippedname = get_symbol(strippedsym);
return get_klass_by_name_impl(accessing_klass, cpool, strippedname, require_local); return get_klass_by_name_impl(accessing_klass, cpool, strippedname, require_local);
} }
@ -466,18 +464,17 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
// we must build an array type around it. The CI requires array klasses // we must build an array type around it. The CI requires array klasses
// to be loaded if their element klasses are loaded, except when memory // to be loaded if their element klasses are loaded, except when memory
// is exhausted. // is exhausted.
if (sym->char_at(0) == JVM_SIGNATURE_ARRAY && if (Signature::is_array(sym) &&
(sym->char_at(1) == JVM_SIGNATURE_ARRAY || sym->char_at(1) == JVM_SIGNATURE_CLASS)) { (sym->char_at(1) == JVM_SIGNATURE_ARRAY || sym->char_at(1) == JVM_SIGNATURE_CLASS)) {
// We have an unloaded array. // We have an unloaded array.
// Build it on the fly if the element class exists. // Build it on the fly if the element class exists.
TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1, SignatureStream ss(sym, false);
sym->utf8_length()-1); ss.skip_array_prefix(1);
// Get element ciKlass recursively. // Get element ciKlass recursively.
ciKlass* elem_klass = ciKlass* elem_klass =
get_klass_by_name_impl(accessing_klass, get_klass_by_name_impl(accessing_klass,
cpool, cpool,
get_symbol(elem_sym), get_symbol(ss.as_symbol()),
require_local); require_local);
if (elem_klass != NULL && elem_klass->is_loaded()) { if (elem_klass != NULL && elem_klass->is_loaded()) {
// Now make an array for it // Now make an array for it
@ -609,7 +606,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
} }
BasicType bt = T_OBJECT; BasicType bt = T_OBJECT;
if (cpool->tag_at(index).is_dynamic_constant()) if (cpool->tag_at(index).is_dynamic_constant())
bt = FieldType::basic_type(cpool->uncached_signature_ref_at(index)); bt = Signature::basic_type(cpool->uncached_signature_ref_at(index));
if (is_reference_type(bt)) { if (is_reference_type(bt)) {
} else { } else {
// we have to unbox the primitive value // we have to unbox the primitive value
@ -791,6 +788,8 @@ Method* ciEnv::lookup_method(ciInstanceKlass* accessor,
ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool, ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
int index, Bytecodes::Code bc, int index, Bytecodes::Code bc,
ciInstanceKlass* accessor) { ciInstanceKlass* accessor) {
assert(cpool.not_null(), "need constant pool");
assert(accessor != NULL, "need origin of access");
if (bc == Bytecodes::_invokedynamic) { if (bc == Bytecodes::_invokedynamic) {
ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index); ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
bool is_resolved = !cpce->is_f1_null(); bool is_resolved = !cpce->is_f1_null();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -86,7 +86,7 @@ ciField::ciField(ciInstanceKlass* klass, int index) :
Symbol* signature = cpool->symbol_at(sig_index); Symbol* signature = cpool->symbol_at(sig_index);
_signature = ciEnv::current(THREAD)->get_symbol(signature); _signature = ciEnv::current(THREAD)->get_symbol(signature);
BasicType field_type = FieldType::basic_type(signature); BasicType field_type = Signature::basic_type(signature);
// If the field is a pointer type, get the klass of the // If the field is a pointer type, get the klass of the
// field. // field.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -44,6 +44,7 @@ class ciKlass : public ciType {
friend class ciMethod; friend class ciMethod;
friend class ciMethodData; friend class ciMethodData;
friend class ciObjArrayKlass; friend class ciObjArrayKlass;
friend class ciSignature;
friend class ciReceiverTypeData; friend class ciReceiverTypeData;
private: private:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -108,37 +108,23 @@ ciSymbol* ciObjArrayKlass::construct_array_name(ciSymbol* element_name,
int dimension) { int dimension) {
EXCEPTION_CONTEXT; EXCEPTION_CONTEXT;
int element_len = element_name->utf8_length(); int element_len = element_name->utf8_length();
int buflen = dimension + element_len + 3; // '['+ + 'L'? + (element) + ';'? + '\0'
char* name = CURRENT_THREAD_ENV->name_buffer(buflen);
int pos = 0;
for ( ; pos < dimension; pos++) {
name[pos] = JVM_SIGNATURE_ARRAY;
}
Symbol* base_name_sym = element_name->get_symbol(); Symbol* base_name_sym = element_name->get_symbol();
char* name;
if (base_name_sym->char_at(0) == JVM_SIGNATURE_ARRAY || if (Signature::is_array(base_name_sym) ||
(base_name_sym->char_at(0) == JVM_SIGNATURE_CLASS && // watch package name 'Lxx' Signature::has_envelope(base_name_sym)) {
base_name_sym->char_at(element_len-1) == JVM_SIGNATURE_ENDCLASS)) { strncpy(&name[pos], (char*)element_name->base(), element_len);
name[pos + element_len] = '\0';
int new_len = element_len + dimension + 1; // for the ['s and '\0'
name = CURRENT_THREAD_ENV->name_buffer(new_len);
int pos = 0;
for ( ; pos < dimension; pos++) {
name[pos] = JVM_SIGNATURE_ARRAY;
}
strncpy(name+pos, (char*)element_name->base(), element_len);
name[new_len-1] = '\0';
} else { } else {
int new_len = 3 // for L, ;, and '\0'
+ dimension // for ['s
+ element_len;
name = CURRENT_THREAD_ENV->name_buffer(new_len);
int pos = 0;
for ( ; pos < dimension; pos++) {
name[pos] = JVM_SIGNATURE_ARRAY;
}
name[pos++] = JVM_SIGNATURE_CLASS; name[pos++] = JVM_SIGNATURE_CLASS;
strncpy(name+pos, (char*)element_name->base(), element_len); strncpy(&name[pos], (char*)element_name->base(), element_len);
name[new_len-2] = JVM_SIGNATURE_ENDCLASS; name[pos + element_len] = JVM_SIGNATURE_ENDCLASS;
name[new_len-1] = '\0'; name[pos + element_len + 1] = '\0';
} }
return ciSymbol::make(name); return ciSymbol::make(name);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -46,7 +46,6 @@
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
@ -418,6 +417,7 @@ ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder,
ciSymbol* name, ciSymbol* name,
ciSymbol* signature, ciSymbol* signature,
ciInstanceKlass* accessor) { ciInstanceKlass* accessor) {
assert(accessor != NULL, "need origin of access");
ciSignature* that = NULL; ciSignature* that = NULL;
for (int i = 0; i < _unloaded_methods->length(); i++) { for (int i = 0; i < _unloaded_methods->length(); i++) {
ciMethod* entry = _unloaded_methods->at(i); ciMethod* entry = _unloaded_methods->at(i);
@ -488,20 +488,14 @@ ciKlass* ciObjectFactory::get_unloaded_klass(ciKlass* accessing_klass,
// unloaded InstanceKlass. Deal with both. // unloaded InstanceKlass. Deal with both.
if (name->char_at(0) == JVM_SIGNATURE_ARRAY) { if (name->char_at(0) == JVM_SIGNATURE_ARRAY) {
// Decompose the name.' // Decompose the name.'
FieldArrayInfo fd; SignatureStream ss(name->get_symbol(), false);
BasicType element_type = FieldType::get_array_info(name->get_symbol(), int dimension = ss.skip_array_prefix(); // skip all '['s
fd, THREAD); BasicType element_type = ss.type();
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
CURRENT_THREAD_ENV->record_out_of_memory_failure();
return ciEnv::_unloaded_ciobjarrayklass;
}
int dimension = fd.dimension();
assert(element_type != T_ARRAY, "unsuccessful decomposition"); assert(element_type != T_ARRAY, "unsuccessful decomposition");
ciKlass* element_klass = NULL; ciKlass* element_klass = NULL;
if (element_type == T_OBJECT) { if (element_type == T_OBJECT) {
ciEnv *env = CURRENT_THREAD_ENV; ciEnv *env = CURRENT_THREAD_ENV;
ciSymbol* ci_name = env->get_symbol(fd.object_key()); ciSymbol* ci_name = env->get_symbol(ss.as_symbol());
element_klass = element_klass =
env->get_klass_by_name(accessing_klass, ci_name, false)->as_instance_klass(); env->get_klass_by_name(accessing_klass, ci_name, false)->as_instance_klass();
} else { } else {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -40,6 +40,7 @@
ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* symbol) { ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* symbol) {
ASSERT_IN_VM; ASSERT_IN_VM;
EXCEPTION_CONTEXT; EXCEPTION_CONTEXT;
assert(accessing_klass != NULL, "need origin of access");
_accessing_klass = accessing_klass; _accessing_klass = accessing_klass;
_symbol = symbol; _symbol = symbol;
@ -55,11 +56,10 @@ ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpo
for (; ; ss.next()) { for (; ; ss.next()) {
// Process one element of the signature // Process one element of the signature
ciType* type; ciType* type;
if (!ss.is_object()) { if (!ss.is_reference()) {
type = ciType::make(ss.type()); type = ciType::make(ss.type());
} else { } else {
Symbol* name = ss.as_symbol(); ciSymbol* klass_name = env->get_symbol(ss.as_symbol());
ciSymbol* klass_name = env->get_symbol(name);
type = env->get_klass_by_name_impl(_accessing_klass, cpool, klass_name, false); type = env->get_klass_by_name_impl(_accessing_klass, cpool, klass_name, false);
} }
_types->append(type); _types->append(type);

View file

@ -665,7 +665,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
"Illegal zero length constant pool entry at %d in class %s", "Illegal zero length constant pool entry at %d in class %s",
name_index, CHECK); name_index, CHECK);
if (sig->char_at(0) == JVM_SIGNATURE_FUNC) { if (Signature::is_method(sig)) {
// Format check method name and signature // Format check method name and signature
verify_legal_method_name(name, CHECK); verify_legal_method_name(name, CHECK);
verify_legal_method_signature(name, sig, CHECK); verify_legal_method_signature(name, sig, CHECK);
@ -690,9 +690,8 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
const Symbol* const signature = cp->symbol_at(signature_ref_index); const Symbol* const signature = cp->symbol_at(signature_ref_index);
if (_need_verify) { if (_need_verify) {
// CONSTANT_Dynamic's name and signature are verified above, when iterating NameAndType_info. // CONSTANT_Dynamic's name and signature are verified above, when iterating NameAndType_info.
// Need only to be sure signature is non-zero length and the right type. // Need only to be sure signature is the right type.
if (signature->utf8_length() == 0 || if (Signature::is_method(signature)) {
signature->char_at(0) == JVM_SIGNATURE_FUNC) {
throwIllegalSignature("CONSTANT_Dynamic", name, signature, CHECK); throwIllegalSignature("CONSTANT_Dynamic", name, signature, CHECK);
} }
} }
@ -716,8 +715,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
if (_need_verify) { if (_need_verify) {
// Field name and signature are verified above, when iterating NameAndType_info. // Field name and signature are verified above, when iterating NameAndType_info.
// Need only to be sure signature is non-zero length and the right type. // Need only to be sure signature is non-zero length and the right type.
if (signature->utf8_length() == 0 || if (Signature::is_method(signature)) {
signature->char_at(0) == JVM_SIGNATURE_FUNC) {
throwIllegalSignature("Field", name, signature, CHECK); throwIllegalSignature("Field", name, signature, CHECK);
} }
} }
@ -725,8 +723,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
if (_need_verify) { if (_need_verify) {
// Method name and signature are verified above, when iterating NameAndType_info. // Method name and signature are verified above, when iterating NameAndType_info.
// Need only to be sure signature is non-zero length and the right type. // Need only to be sure signature is non-zero length and the right type.
if (signature->utf8_length() == 0 || if (!Signature::is_method(signature)) {
signature->char_at(0) != JVM_SIGNATURE_FUNC) {
throwIllegalSignature("Method", name, signature, CHECK); throwIllegalSignature("Method", name, signature, CHECK);
} }
} }
@ -1723,7 +1720,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
injected[n].signature_index, injected[n].signature_index,
0); 0);
const BasicType type = FieldType::basic_type(injected[n].signature()); const BasicType type = Signature::basic_type(injected[n].signature());
// Remember how many oops we encountered and compute allocation type // Remember how many oops we encountered and compute allocation type
const FieldAllocationType atype = fac->update(false, type); const FieldAllocationType atype = fac->update(false, type);
@ -2796,21 +2793,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
m->set_constants(_cp); m->set_constants(_cp);
m->set_name_index(name_index); m->set_name_index(name_index);
m->set_signature_index(signature_index); m->set_signature_index(signature_index);
m->compute_from_signature(cp->symbol_at(signature_index));
ResultTypeFinder rtf(cp->symbol_at(signature_index)); assert(args_size < 0 || args_size == m->size_of_parameters(), "");
m->constMethod()->set_result_type(rtf.type());
if (args_size >= 0) {
m->set_size_of_parameters(args_size);
} else {
m->compute_size_of_parameters(THREAD);
}
#ifdef ASSERT
if (args_size >= 0) {
m->compute_size_of_parameters(THREAD);
assert(args_size == m->size_of_parameters(), "");
}
#endif
// Fill in code attribute information // Fill in code attribute information
m->set_max_stack(max_stack); m->set_max_stack(max_stack);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -34,7 +34,6 @@
#include "logging/logTag.hpp" #include "logging/logTag.hpp"
#include "memory/metaspaceShared.hpp" #include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "utilities/defaultStream.hpp" #include "utilities/defaultStream.hpp"
@ -338,7 +337,7 @@ Klass* ClassListParser::load_current_class(TRAPS) {
error("If source location is not specified, interface(s) must not be specified"); error("If source location is not specified, interface(s) must not be specified");
} }
bool non_array = !FieldType::is_array(class_name_symbol); bool non_array = !Signature::is_array(class_name_symbol);
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
if (non_array) { if (non_array) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -901,8 +901,7 @@ static Method* new_method(
m->set_constants(NULL); // This will get filled in later m->set_constants(NULL); // This will get filled in later
m->set_name_index(cp->utf8(name)); m->set_name_index(cp->utf8(name));
m->set_signature_index(cp->utf8(sig)); m->set_signature_index(cp->utf8(sig));
ResultTypeFinder rtf(sig); m->compute_from_signature(sig);
m->constMethod()->set_result_type(rtf.type());
m->set_size_of_parameters(params); m->set_size_of_parameters(params);
m->set_max_stack(max_stack); m->set_max_stack(max_stack);
m->set_max_locals(params); m->set_max_locals(params);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -27,7 +27,6 @@
#include "classfile/placeholders.hpp" #include "classfile/placeholders.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/fieldType.hpp"
#include "utilities/hashtable.inline.hpp" #include "utilities/hashtable.inline.hpp"
// Placeholder methods // Placeholder methods

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -28,7 +28,6 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/constantPool.hpp" #include "oops/constantPool.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame, StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,

View file

@ -74,7 +74,6 @@
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "runtime/arguments.hpp" #include "runtime/arguments.hpp"
#include "runtime/biasedLocking.hpp" #include "runtime/biasedLocking.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
@ -240,7 +239,7 @@ Klass* SystemDictionary::resolve_or_fail(Symbol* class_name,
// Forwards to resolve_array_class_or_null or resolve_instance_class_or_null // Forwards to resolve_array_class_or_null or resolve_instance_class_or_null
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
if (FieldType::is_array(class_name)) { if (Signature::is_array(class_name)) {
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD); return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
} else { } else {
return resolve_instance_class_or_null_helper(class_name, class_loader, protection_domain, THREAD); return resolve_instance_class_or_null_helper(class_name, class_loader, protection_domain, THREAD);
@ -252,8 +251,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null_helper(Symbol* c
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS) { TRAPS) {
assert(class_name != NULL && !FieldType::is_array(class_name), "must be"); assert(class_name != NULL && !Signature::is_array(class_name), "must be");
if (FieldType::is_obj(class_name)) { if (Signature::has_envelope(class_name)) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
// Ignore wrapping L and ;. // Ignore wrapping L and ;.
TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1, TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
@ -274,24 +273,24 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS) { TRAPS) {
assert(FieldType::is_array(class_name), "must be array"); assert(Signature::is_array(class_name), "must be array");
ResourceMark rm(THREAD);
SignatureStream ss(class_name, false);
int ndims = ss.skip_array_prefix(); // skip all '['s
Klass* k = NULL; Klass* k = NULL;
FieldArrayInfo fd; BasicType t = ss.type();
// dimension and object_key in FieldArrayInfo are assigned as a side-effect if (ss.has_envelope()) {
// of this call Symbol* obj_class = ss.as_symbol();
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_NULL); k = SystemDictionary::resolve_instance_class_or_null(obj_class,
if (t == T_OBJECT) {
// naked oop "k" is OK here -- we assign back into it
k = SystemDictionary::resolve_instance_class_or_null(fd.object_key(),
class_loader, class_loader,
protection_domain, protection_domain,
CHECK_NULL); CHECK_NULL);
if (k != NULL) { if (k != NULL) {
k = k->array_klass(fd.dimension(), CHECK_NULL); k = k->array_klass(ndims, CHECK_NULL);
} }
} else { } else {
k = Universe::typeArrayKlassObj(t); k = Universe::typeArrayKlassObj(t);
k = TypeArrayKlass::cast(k)->array_klass(fd.dimension(), CHECK_NULL); k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
} }
return k; return k;
} }
@ -342,7 +341,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
Handle protection_domain, Handle protection_domain,
bool is_superclass, bool is_superclass,
TRAPS) { TRAPS) {
assert(!FieldType::is_array(super_name), "invalid super class name"); assert(!Signature::is_array(super_name), "invalid super class name");
#if INCLUDE_CDS #if INCLUDE_CDS
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
// Special processing for handling UNREGISTERED shared classes. // Special processing for handling UNREGISTERED shared classes.
@ -654,8 +653,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS) { TRAPS) {
assert(name != NULL && !FieldType::is_array(name) && assert(name != NULL && !Signature::is_array(name) &&
!FieldType::is_obj(name), "invalid class name"); !Signature::has_envelope(name), "invalid class name");
EventClassLoad class_load_start_event; EventClassLoad class_load_start_event;
@ -960,19 +959,21 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
Klass* k = NULL; Klass* k = NULL;
assert(class_name != NULL, "class name must be non NULL"); assert(class_name != NULL, "class name must be non NULL");
if (FieldType::is_array(class_name)) { if (Signature::is_array(class_name)) {
// The name refers to an array. Parse the name. // The name refers to an array. Parse the name.
// dimension and object_key in FieldArrayInfo are assigned as a // dimension and object_key in FieldArrayInfo are assigned as a
// side-effect of this call // side-effect of this call
FieldArrayInfo fd; SignatureStream ss(class_name, false);
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL)); int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
if (t != T_OBJECT) { if (t != T_OBJECT) {
k = Universe::typeArrayKlassObj(t); k = Universe::typeArrayKlassObj(t);
} else { } else {
k = SystemDictionary::find(fd.object_key(), class_loader, protection_domain, THREAD); Symbol* obj_class = ss.as_symbol();
k = SystemDictionary::find(obj_class, class_loader, protection_domain, THREAD);
} }
if (k != NULL) { if (k != NULL) {
k = k->array_klass_or_null(fd.dimension()); k = k->array_klass_or_null(ndims);
} }
} else { } else {
k = find(class_name, class_loader, protection_domain, THREAD); k = find(class_name, class_loader, protection_domain, THREAD);
@ -2167,20 +2168,21 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass(
// Now look to see if it has been loaded elsewhere, and is subject to // Now look to see if it has been loaded elsewhere, and is subject to
// a loader constraint that would require this loader to return the // a loader constraint that would require this loader to return the
// klass that is already loaded. // klass that is already loaded.
if (FieldType::is_array(class_name)) { if (Signature::is_array(class_name)) {
// For array classes, their Klass*s are not kept in the // For array classes, their Klass*s are not kept in the
// constraint table. The element Klass*s are. // constraint table. The element Klass*s are.
FieldArrayInfo fd; SignatureStream ss(class_name, false);
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL)); int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
if (t != T_OBJECT) { if (t != T_OBJECT) {
klass = Universe::typeArrayKlassObj(t); klass = Universe::typeArrayKlassObj(t);
} else { } else {
MutexLocker mu(THREAD, SystemDictionary_lock); MutexLocker mu(THREAD, SystemDictionary_lock);
klass = constraints()->find_constrained_klass(fd.object_key(), class_loader); klass = constraints()->find_constrained_klass(ss.as_symbol(), class_loader);
} }
// If element class already loaded, allocate array klass // If element class already loaded, allocate array klass
if (klass != NULL) { if (klass != NULL) {
klass = klass->array_klass_or_null(fd.dimension()); klass = klass->array_klass_or_null(ndims);
} }
} else { } else {
MutexLocker mu(THREAD, SystemDictionary_lock); MutexLocker mu(THREAD, SystemDictionary_lock);
@ -2200,21 +2202,22 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
ClassLoaderData* loader_data2 = class_loader_data(class_loader2); ClassLoaderData* loader_data2 = class_loader_data(class_loader2);
Symbol* constraint_name = NULL; Symbol* constraint_name = NULL;
// Needs to be in same scope as constraint_name in case a Symbol is created and
// assigned to constraint_name. if (!Signature::is_array(class_name)) {
FieldArrayInfo fd;
if (!FieldType::is_array(class_name)) {
constraint_name = class_name; constraint_name = class_name;
} else { } else {
// For array classes, their Klass*s are not kept in the // For array classes, their Klass*s are not kept in the
// constraint table. The element classes are. // constraint table. The element classes are.
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(false)); SignatureStream ss(class_name, false);
// primitive types always pass ss.skip_array_prefix(); // skip all '['s
if (t != T_OBJECT) { if (!ss.has_envelope()) {
return true; return true; // primitive types always pass
} else {
constraint_name = fd.object_key();
} }
constraint_name = ss.as_symbol();
// Increment refcount to keep constraint_name alive after
// SignatureStream is destructed. It will be decremented below
// before returning.
constraint_name->increment_refcount();
} }
Dictionary* dictionary1 = loader_data1->dictionary(); Dictionary* dictionary1 = loader_data1->dictionary();
@ -2227,8 +2230,12 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
MutexLocker mu_s(THREAD, SystemDictionary_lock); MutexLocker mu_s(THREAD, SystemDictionary_lock);
InstanceKlass* klass1 = find_class(d_hash1, constraint_name, dictionary1); InstanceKlass* klass1 = find_class(d_hash1, constraint_name, dictionary1);
InstanceKlass* klass2 = find_class(d_hash2, constraint_name, dictionary2); InstanceKlass* klass2 = find_class(d_hash2, constraint_name, dictionary2);
return constraints()->add_entry(constraint_name, klass1, class_loader1, bool result = constraints()->add_entry(constraint_name, klass1, class_loader1,
klass2, class_loader2); klass2, class_loader2);
if (Signature::is_array(class_name)) {
constraint_name->decrement_refcount();
}
return result;
} }
} }
@ -2325,15 +2332,16 @@ Symbol* SystemDictionary::check_signature_loaders(Symbol* signature,
return NULL; return NULL;
} }
SignatureStream sig_strm(signature, is_method); for (SignatureStream ss(signature, is_method); !ss.is_done(); ss.next()) {
while (!sig_strm.is_done()) { if (ss.is_reference()) {
if (sig_strm.is_object()) { Symbol* sig = ss.as_symbol();
Symbol* sig = sig_strm.as_symbol(); // Note: In the future, if template-like types can take
// arguments, we will want to recognize them and dig out class
// names hiding inside the argument lists.
if (!add_loader_constraint(sig, loader1, loader2, THREAD)) { if (!add_loader_constraint(sig, loader1, loader2, THREAD)) {
return sig; return sig;
} }
} }
sig_strm.next();
} }
return NULL; return NULL;
} }
@ -2474,14 +2482,6 @@ static bool is_always_visible_class(oop mirror) {
InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass())); // java.lang.invoke InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass())); // java.lang.invoke
} }
// Return the Java mirror (java.lang.Class instance) for a single-character
// descriptor. This result, when available, is the same as produced by the
// heavier API point of the same name that takes a Symbol.
oop SystemDictionary::find_java_mirror_for_type(char signature_char) {
return java_lang_Class::primitive_mirror(char2type(signature_char));
}
// Find or construct the Java mirror (java.lang.Class instance) for a // Find or construct the Java mirror (java.lang.Class instance) for a
// for the given field type signature, as interpreted relative to the // for the given field type signature, as interpreted relative to the
// given class loader. Handles primitives, void, references, arrays, // given class loader. Handles primitives, void, references, arrays,
@ -2498,19 +2498,17 @@ Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()), assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()),
"one or the other, or perhaps neither"); "one or the other, or perhaps neither");
Symbol* type = signature; SignatureStream ss(signature, false);
// What we have here must be a valid field descriptor, // What we have here must be a valid field descriptor,
// and all valid field descriptors are supported. // and all valid field descriptors are supported.
// Produce the same java.lang.Class that reflection reports. // Produce the same java.lang.Class that reflection reports.
if (type->utf8_length() == 1) { if (ss.is_primitive() || (ss.type() == T_VOID)) {
// It's a primitive. (Void has a primitive mirror too.) // It's a primitive. (Void has a primitive mirror too.)
char ch = type->char_at(0); return Handle(THREAD, java_lang_Class::primitive_mirror(ss.type()));
assert(is_java_primitive(char2type(ch)) || ch == JVM_SIGNATURE_VOID, "");
return Handle(THREAD, find_java_mirror_for_type(ch));
} else if (FieldType::is_obj(type) || FieldType::is_array(type)) { } else if (ss.is_reference()) {
// It's a reference type. // It's a reference type.
if (accessing_klass != NULL) { if (accessing_klass != NULL) {
@ -2519,11 +2517,11 @@ Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
} }
Klass* constant_type_klass; Klass* constant_type_klass;
if (failure_mode == SignatureStream::ReturnNull) { if (failure_mode == SignatureStream::ReturnNull) {
constant_type_klass = resolve_or_null(type, class_loader, protection_domain, constant_type_klass = resolve_or_null(signature, class_loader, protection_domain,
CHECK_(empty)); CHECK_(empty));
} else { } else {
bool throw_error = (failure_mode == SignatureStream::NCDFError); bool throw_error = (failure_mode == SignatureStream::NCDFError);
constant_type_klass = resolve_or_fail(type, class_loader, protection_domain, constant_type_klass = resolve_or_fail(signature, class_loader, protection_domain,
throw_error, CHECK_(empty)); throw_error, CHECK_(empty));
} }
if (constant_type_klass == NULL) { if (constant_type_klass == NULL) {
@ -2586,7 +2584,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
// Use neutral class loader to lookup candidate classes to be placed in the cache. // Use neutral class loader to lookup candidate classes to be placed in the cache.
mirror = ss.as_java_mirror(Handle(), Handle(), mirror = ss.as_java_mirror(Handle(), Handle(),
SignatureStream::ReturnNull, CHECK_(empty)); SignatureStream::ReturnNull, CHECK_(empty));
if (mirror == NULL || (ss.is_object() && !is_always_visible_class(mirror))) { if (mirror == NULL || (ss.is_reference() && !is_always_visible_class(mirror))) {
// Fall back to accessing_klass context. // Fall back to accessing_klass context.
can_be_cached = false; can_be_cached = false;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -497,10 +497,6 @@ public:
failure_mode, THREAD); failure_mode, THREAD);
} }
// fast short-cut for the one-character case:
static oop find_java_mirror_for_type(char signature_char);
// find a java.lang.invoke.MethodType object for a given signature // find a java.lang.invoke.MethodType object for a given signature
// (asks Java to compute it if necessary, except in a compiler thread) // (asks Java to compute it if necessary, except in a compiler thread)
static Handle find_method_handle_type(Symbol* signature, static Handle find_method_handle_type(Symbol* signature,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -120,24 +120,26 @@ bool VerificationType::is_reference_assignable_from(
VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const { VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const {
assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array"); assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array");
Symbol* component; SignatureStream ss(name(), false);
switch (name()->char_at(1)) { ss.skip_array_prefix(1);
case JVM_SIGNATURE_BOOLEAN: return VerificationType(Boolean); switch (ss.type()) {
case JVM_SIGNATURE_BYTE: return VerificationType(Byte); case T_BOOLEAN: return VerificationType(Boolean);
case JVM_SIGNATURE_CHAR: return VerificationType(Char); case T_BYTE: return VerificationType(Byte);
case JVM_SIGNATURE_SHORT: return VerificationType(Short); case T_CHAR: return VerificationType(Char);
case JVM_SIGNATURE_INT: return VerificationType(Integer); case T_SHORT: return VerificationType(Short);
case JVM_SIGNATURE_LONG: return VerificationType(Long); case T_INT: return VerificationType(Integer);
case JVM_SIGNATURE_FLOAT: return VerificationType(Float); case T_LONG: return VerificationType(Long);
case JVM_SIGNATURE_DOUBLE: return VerificationType(Double); case T_FLOAT: return VerificationType(Float);
case JVM_SIGNATURE_ARRAY: case T_DOUBLE: return VerificationType(Double);
component = context->create_temporary_symbol( case T_ARRAY:
name(), 1, name()->utf8_length()); case T_OBJECT: {
return VerificationType::reference_type(component); guarantee(ss.is_reference(), "unchecked verifier input?");
case JVM_SIGNATURE_CLASS: Symbol* component = ss.as_symbol();
component = context->create_temporary_symbol( // Create another symbol to save as signature stream unreferences this symbol.
name(), 2, name()->utf8_length() - 1); Symbol* component_copy = context->create_temporary_symbol(component);
return VerificationType::reference_type(component); assert(component_copy == component, "symbols don't match");
return VerificationType::reference_type(component_copy);
}
default: default:
// Met an invalid type signature, e.g. [X // Met an invalid type signature, e.g. [X
return VerificationType::bogus_type(); return VerificationType::bogus_type();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -99,13 +99,13 @@ void vmSymbols::initialize(TRAPS) {
_type_signatures[T_SHORT] = short_signature(); _type_signatures[T_SHORT] = short_signature();
_type_signatures[T_BOOLEAN] = bool_signature(); _type_signatures[T_BOOLEAN] = bool_signature();
_type_signatures[T_VOID] = void_signature(); _type_signatures[T_VOID] = void_signature();
// no single signatures for T_OBJECT or T_ARRAY
#ifdef ASSERT #ifdef ASSERT
for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) { for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) {
Symbol* s = _type_signatures[i]; Symbol* s = _type_signatures[i];
if (s == NULL) continue; if (s == NULL) continue;
BasicType st = signature_type(s); SignatureStream ss(s, false);
assert(st == i, ""); assert(ss.type() == i, "matching signature");
assert(!ss.is_reference(), "no single-char signature for T_OBJECT, etc.");
} }
#endif #endif
} }
@ -209,20 +209,6 @@ void vmSymbols::serialize(SerializeClosure* soc) {
soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures)); soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures));
} }
BasicType vmSymbols::signature_type(const Symbol* s) {
assert(s != NULL, "checking");
if (s->utf8_length() == 1) {
BasicType result = char2type(s->char_at(0));
if (is_java_primitive(result) || result == T_VOID) {
assert(s == _type_signatures[result], "");
return result;
}
}
return T_OBJECT;
}
static int mid_hint = (int)vmSymbols::FIRST_SID+1; static int mid_hint = (int)vmSymbols::FIRST_SID+1;
#ifndef PRODUCT #ifndef PRODUCT

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -1566,8 +1566,6 @@ class vmSymbols: AllStatic {
assert(_type_signatures[t] != NULL, "domain check"); assert(_type_signatures[t] != NULL, "domain check");
return _type_signatures[t]; return _type_signatures[t];
} }
// inverse of type_signature; returns T_OBJECT if s is not recognized
static BasicType signature_type(const Symbol* s);
static Symbol* symbol_at(SID id) { static Symbol* symbol_at(SID id) {
assert(id >= FIRST_SID && id < SID_LIMIT, "oob"); assert(id >= FIRST_SID && id < SID_LIMIT, "oob");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -3151,13 +3151,11 @@ void nmethod::print_nmethod_labels(outputStream* stream, address block_begin, bo
m->method_holder()->print_value_on(stream); m->method_holder()->print_value_on(stream);
} else { } else {
bool did_name = false; bool did_name = false;
if (!at_this && ss.is_object()) { if (!at_this && ss.is_reference()) {
Symbol* name = ss.as_symbol_or_null(); Symbol* name = ss.as_symbol();
if (name != NULL) {
name->print_value_on(stream); name->print_value_on(stream);
did_name = true; did_name = true;
} }
}
if (!did_name) if (!did_name)
stream->print("%s", type2name(t)); stream->print("%s", type2name(t));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -271,7 +271,8 @@ void MethodMatcher::parse_method_pattern(char*& line, const char*& error_msg, Me
} }
if ((strchr(method_name, JVM_SIGNATURE_SPECIAL) != NULL) || if ((strchr(method_name, JVM_SIGNATURE_SPECIAL) != NULL) ||
(strchr(method_name, JVM_SIGNATURE_ENDSPECIAL) != NULL)) { (strchr(method_name, JVM_SIGNATURE_ENDSPECIAL) != NULL)) {
if ((strncmp("<init>", method_name, 255) != 0) && (strncmp("<clinit>", method_name, 255) != 0)) { if (!vmSymbols::object_initializer_name()->equals(method_name) &&
!vmSymbols::class_initializer_name()->equals(method_name)) {
error_msg = "Chars '<' and '>' only allowed in <init> and <clinit>"; error_msg = "Chars '<' and '>' only allowed in <init> and <clinit>";
return; return;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -28,7 +28,6 @@
#include "oops/constantPool.hpp" #include "oops/constantPool.hpp"
#include "oops/cpCache.inline.hpp" #include "oops/cpCache.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/safepoint.hpp" #include "runtime/safepoint.hpp"
#include "runtime/signature.hpp" #include "runtime/signature.hpp"

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019 SAP SE. All rights reserved. * Copyright (c) 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -975,7 +975,7 @@ int ExceptionMessageBuilder::do_instruction(int bci) {
// Simulate the bytecode: pop the address, push the 'value' loaded // Simulate the bytecode: pop the address, push the 'value' loaded
// from the field. // from the field.
stack->pop(1 - Bytecodes::depth(code)); stack->pop(1 - Bytecodes::depth(code));
stack->push(bci, char2type((char) signature->char_at(0))); stack->push(bci, Signature::basic_type(signature));
break; break;
} }
@ -986,8 +986,8 @@ int ExceptionMessageBuilder::do_instruction(int bci) {
int name_and_type_index = cp->name_and_type_ref_index_at(cp_index); int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
int type_index = cp->signature_ref_index_at(name_and_type_index); int type_index = cp->signature_ref_index_at(name_and_type_index);
Symbol* signature = cp->symbol_at(type_index); Symbol* signature = cp->symbol_at(type_index);
ResultTypeFinder result_type(signature); BasicType bt = Signature::basic_type(signature);
stack->pop(type2size[char2type((char) signature->char_at(0))] - Bytecodes::depth(code) - 1); stack->pop(type2size[bt] - Bytecodes::depth(code) - 1);
break; break;
} }
@ -1137,7 +1137,8 @@ int ExceptionMessageBuilder::get_NPE_null_slot(int bci) {
int name_and_type_index = cp->name_and_type_ref_index_at(cp_index); int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
int type_index = cp->signature_ref_index_at(name_and_type_index); int type_index = cp->signature_ref_index_at(name_and_type_index);
Symbol* signature = cp->symbol_at(type_index); Symbol* signature = cp->symbol_at(type_index);
return type2size[char2type((char) signature->char_at(0))]; BasicType bt = Signature::basic_type(signature);
return type2size[bt];
} }
case Bytecodes::_invokevirtual: case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial: case Bytecodes::_invokespecial:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -1369,7 +1369,7 @@ void SignatureHandlerLibrary::add(const methodHandle& method) {
// use slow signature handler if we can't do better // use slow signature handler if we can't do better
int handler_index = -1; int handler_index = -1;
// check if we can use customized (fast) signature handler // check if we can use customized (fast) signature handler
if (UseFastSignatureHandlers && method->size_of_parameters() <= Fingerprinter::max_size_of_parameters) { if (UseFastSignatureHandlers && method->size_of_parameters() <= Fingerprinter::fp_max_size_of_parameters) {
// use customized signature handler // use customized signature handler
MutexLocker mu(SignatureHandlerLibrary_lock); MutexLocker mu(SignatureHandlerLibrary_lock);
// make sure data structure is initialized // make sure data structure is initialized

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -257,7 +257,7 @@ class MaskFillerForNative: public NativeSignatureIterator {
} }
void generate() { void generate() {
NativeSignatureIterator::iterate(); iterate();
} }
}; };

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -330,7 +330,7 @@ void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide,
tag.is_string() || tag.is_string() ||
(tag.is_dynamic_constant() && (tag.is_dynamic_constant() &&
// keep regular ldc interpreter logic for condy primitives // keep regular ldc interpreter logic for condy primitives
is_reference_type(FieldType::basic_type(_pool->uncached_signature_ref_at(cp_index)))) is_reference_type(Signature::basic_type(_pool->uncached_signature_ref_at(cp_index))))
) { ) {
int ref_index = cp_entry_to_resolved_references(cp_index); int ref_index = cp_entry_to_resolved_references(cp_index);
if (is_wide) { if (is_wide) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -72,13 +72,11 @@ Klass* CompilerRuntime::resolve_klass_helper(JavaThread *thread, const char* nam
Handle loader(THREAD, caller->method_holder()->class_loader()); Handle loader(THREAD, caller->method_holder()->class_loader());
Handle protection_domain(THREAD, caller->method_holder()->protection_domain()); Handle protection_domain(THREAD, caller->method_holder()->protection_domain());
// Ignore wrapping L and ;
if (name[0] == JVM_SIGNATURE_CLASS) {
assert(len > 2, "small name %s", name);
name++;
len -= 2;
}
TempNewSymbol sym = SymbolTable::new_symbol(name, len); TempNewSymbol sym = SymbolTable::new_symbol(name, len);
if (sym != NULL && Signature::has_envelope(sym)) {
// Ignore wrapping L and ;
sym = Signature::strip_envelope(sym);
}
if (sym == NULL) { if (sym == NULL) {
return NULL; return NULL;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -539,30 +539,25 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla
JVMCI_THROW_MSG_NULL(ClassNotFoundException, str); JVMCI_THROW_MSG_NULL(ClassNotFoundException, str);
} }
} else { } else {
if (class_name->char_at(0) == JVM_SIGNATURE_CLASS && if (Signature::has_envelope(class_name)) {
class_name->char_at(class_name->utf8_length()-1) == JVM_SIGNATURE_ENDCLASS) {
// This is a name from a signature. Strip off the trimmings. // This is a name from a signature. Strip off the trimmings.
// Call recursive to keep scope of strippedsym. // Call recursive to keep scope of strippedsym.
TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1, TempNewSymbol strippedsym = Signature::strip_envelope(class_name);
class_name->utf8_length()-2);
resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0); resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0);
} else if (FieldType::is_array(class_name)) { } else if (Signature::is_array(class_name)) {
FieldArrayInfo fd; SignatureStream ss(class_name, false);
// dimension and object_key in FieldArrayInfo are assigned as a side-effect int ndim = ss.skip_array_prefix();
// of this call if (ss.type() == T_OBJECT) {
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_0); Symbol* strippedsym = ss.as_symbol();
if (t == T_OBJECT) {
TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
class_name->utf8_length()-2-fd.dimension());
resolved_klass = SystemDictionary::find(strippedsym, resolved_klass = SystemDictionary::find(strippedsym,
class_loader, class_loader,
protection_domain, protection_domain,
CHECK_0); CHECK_0);
if (!resolved_klass.is_null()) { if (!resolved_klass.is_null()) {
resolved_klass = resolved_klass->array_klass(fd.dimension(), CHECK_0); resolved_klass = resolved_klass->array_klass(ndim, CHECK_0);
} }
} else { } else {
resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(t))->array_klass(fd.dimension(), CHECK_0); resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(ss.type()))->array_klass(ndim, CHECK_0);
} }
} else { } else {
resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_0); resolved_klass = SystemDictionary::find(class_name, class_loader, protection_domain, CHECK_0);
@ -1036,18 +1031,18 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject
JavaCallArguments jca(mh->size_of_parameters()); JavaCallArguments jca(mh->size_of_parameters());
JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
JavaValue result(jap.get_ret_type()); JavaValue result(jap.return_type());
jca.set_alternative_target(nm); jca.set_alternative_target(nm);
JavaCalls::call(&result, mh, &jca, CHECK_NULL); JavaCalls::call(&result, mh, &jca, CHECK_NULL);
if (jap.get_ret_type() == T_VOID) { if (jap.return_type() == T_VOID) {
return NULL; return NULL;
} else if (is_reference_type(jap.get_ret_type())) { } else if (is_reference_type(jap.return_type())) {
return JNIHandles::make_local((oop) result.get_jobject()); return JNIHandles::make_local((oop) result.get_jobject());
} else { } else {
jvalue *value = (jvalue *) result.get_value_addr(); jvalue *value = (jvalue *) result.get_value_addr();
// Narrow the value down if required (Important on big endian machines) // Narrow the value down if required (Important on big endian machines)
switch (jap.get_ret_type()) { switch (jap.return_type()) {
case T_BOOLEAN: case T_BOOLEAN:
value->z = (jboolean) value->i; value->z = (jboolean) value->i;
break; break;
@ -1063,7 +1058,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject
default: default:
break; break;
} }
JVMCIObject o = JVMCIENV->create_box(jap.get_ret_type(), value, JVMCI_CHECK_NULL); JVMCIObject o = JVMCIENV->create_box(jap.return_type(), value, JVMCI_CHECK_NULL);
return JVMCIENV->get_jobject(o); return JVMCIENV->get_jobject(o);
} }
C2V_END C2V_END

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -132,7 +132,12 @@ class JavaArgumentUnboxer : public SignatureIterator {
Handle next_arg(BasicType expectedType); Handle next_arg(BasicType expectedType);
public: public:
JavaArgumentUnboxer(Symbol* signature, JavaCallArguments* jca, arrayOop args, bool is_static) : SignatureIterator(signature) { JavaArgumentUnboxer(Symbol* signature,
JavaCallArguments* jca,
arrayOop args,
bool is_static)
: SignatureIterator(signature)
{
this->_return_type = T_ILLEGAL; this->_return_type = T_ILLEGAL;
_jca = jca; _jca = jca;
_index = 0; _index = 0;
@ -140,24 +145,31 @@ class JavaArgumentUnboxer : public SignatureIterator {
if (!is_static) { if (!is_static) {
_jca->push_oop(next_arg(T_OBJECT)); _jca->push_oop(next_arg(T_OBJECT));
} }
iterate(); do_parameters_on(this);
assert(_index == args->length(), "arg count mismatch with signature"); assert(_index == args->length(), "arg count mismatch with signature");
} }
inline void do_bool() { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); } private:
inline void do_char() { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); } friend class SignatureIterator; // so do_parameters_on can call do_type
inline void do_short() { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); } void do_type(BasicType type) {
inline void do_byte() { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); } if (is_reference_type(type)) {
inline void do_int() { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); } _jca->push_oop(next_arg(T_OBJECT));
return;
inline void do_long() { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); } }
inline void do_float() { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); } Handle arg = next_arg(type);
inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); } int box_offset = java_lang_boxing_object::value_offset_in_bytes(type);
switch (type) {
inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); } case T_BOOLEAN: _jca->push_int(arg->bool_field(box_offset)); break;
inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } case T_CHAR: _jca->push_int(arg->char_field(box_offset)); break;
inline void do_array(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } case T_SHORT: _jca->push_int(arg->short_field(box_offset)); break;
inline void do_void() { } case T_BYTE: _jca->push_int(arg->byte_field(box_offset)); break;
case T_INT: _jca->push_int(arg->int_field(box_offset)); break;
case T_LONG: _jca->push_long(arg->long_field(box_offset)); break;
case T_FLOAT: _jca->push_float(arg->float_field(box_offset)); break;
case T_DOUBLE: _jca->push_double(arg->double_field(box_offset)); break;
default: ShouldNotReachHere();
}
}
}; };
class JNIHandleMark : public StackObj { class JNIHandleMark : public StackObj {

View file

@ -67,7 +67,7 @@ ConstMethod::ConstMethod(int byte_code_size,
set_max_locals(0); set_max_locals(0);
set_method_idnum(0); set_method_idnum(0);
set_size_of_parameters(0); set_size_of_parameters(0);
set_result_type(T_VOID); set_result_type((BasicType)0);
} }
// Accessor that copies to metadata. // Accessor that copies to metadata.

View file

@ -49,7 +49,6 @@
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp" #include "oops/typeArrayOop.inline.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/init.hpp" #include "runtime/init.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
@ -728,7 +727,7 @@ char* ConstantPool::string_at_noresolve(int which) {
} }
BasicType ConstantPool::basic_type_for_signature_at(int which) const { BasicType ConstantPool::basic_type_for_signature_at(int which) const {
return FieldType::basic_type(symbol_at(which)); return Signature::basic_type(symbol_at(which));
} }
@ -840,7 +839,7 @@ BasicType ConstantPool::basic_type_for_constant_at(int which) {
tag.is_dynamic_constant_in_error()) { tag.is_dynamic_constant_in_error()) {
// have to look at the signature for this one // have to look at the signature for this one
Symbol* constant_type = uncached_signature_ref_at(which); Symbol* constant_type = uncached_signature_ref_at(which);
return FieldType::basic_type(constant_type); return Signature::basic_type(constant_type);
} }
return tag.basic_type(); return tag.basic_type();
} }
@ -950,7 +949,7 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
save_and_throw_exception(this_cp, index, tag, CHECK_NULL); save_and_throw_exception(this_cp, index, tag, CHECK_NULL);
} }
result_oop = bootstrap_specifier.resolved_value()(); result_oop = bootstrap_specifier.resolved_value()();
BasicType type = FieldType::basic_type(bootstrap_specifier.signature()); BasicType type = Signature::basic_type(bootstrap_specifier.signature());
if (!is_reference_type(type)) { if (!is_reference_type(type)) {
// Make sure the primitive value is properly boxed. // Make sure the primitive value is properly boxed.
// This is a JDK responsibility. // This is a JDK responsibility.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -114,20 +114,20 @@ class ComputeCallStack : public SignatureIterator {
void set(CellTypeState state) { _effect[_idx++] = state; } void set(CellTypeState state) { _effect[_idx++] = state; }
int length() { return _idx; }; int length() { return _idx; };
virtual void do_bool () { set(CellTypeState::value); }; friend class SignatureIterator; // so do_parameters_on can call do_type
virtual void do_char () { set(CellTypeState::value); }; void do_type(BasicType type, bool for_return = false) {
virtual void do_float () { set(CellTypeState::value); }; if (for_return && type == T_VOID) {
virtual void do_byte () { set(CellTypeState::value); }; set(CellTypeState::bottom);
virtual void do_short () { set(CellTypeState::value); }; } else if (is_reference_type(type)) {
virtual void do_int () { set(CellTypeState::value); }; set(CellTypeState::ref);
virtual void do_void () { set(CellTypeState::bottom);}; } else {
virtual void do_object(int begin, int end) { set(CellTypeState::ref); }; assert(is_java_primitive(type), "");
virtual void do_array (int begin, int end) { set(CellTypeState::ref); }; set(CellTypeState::value);
if (is_double_word_type(type)) {
void do_double() { set(CellTypeState::value); set(CellTypeState::value);
set(CellTypeState::value); } }
void do_long () { set(CellTypeState::value); }
set(CellTypeState::value); } }
public: public:
ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {}; ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {};
@ -140,7 +140,7 @@ public:
if (!is_static) if (!is_static)
effect[_idx++] = CellTypeState::ref; effect[_idx++] = CellTypeState::ref;
iterate_parameters(); do_parameters_on(this);
return length(); return length();
}; };
@ -148,7 +148,7 @@ public:
int compute_for_returntype(CellTypeState *effect) { int compute_for_returntype(CellTypeState *effect) {
_idx = 0; _idx = 0;
_effect = effect; _effect = effect;
iterate_returntype(); do_type(return_type(), true);
set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
return length(); return length();
@ -168,20 +168,20 @@ class ComputeEntryStack : public SignatureIterator {
void set(CellTypeState state) { _effect[_idx++] = state; } void set(CellTypeState state) { _effect[_idx++] = state; }
int length() { return _idx; }; int length() { return _idx; };
virtual void do_bool () { set(CellTypeState::value); }; friend class SignatureIterator; // so do_parameters_on can call do_type
virtual void do_char () { set(CellTypeState::value); }; void do_type(BasicType type, bool for_return = false) {
virtual void do_float () { set(CellTypeState::value); }; if (for_return && type == T_VOID) {
virtual void do_byte () { set(CellTypeState::value); }; set(CellTypeState::bottom);
virtual void do_short () { set(CellTypeState::value); }; } else if (is_reference_type(type)) {
virtual void do_int () { set(CellTypeState::value); }; set(CellTypeState::make_slot_ref(_idx));
virtual void do_void () { set(CellTypeState::bottom);}; } else {
virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } assert(is_java_primitive(type), "");
virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); } set(CellTypeState::value);
if (is_double_word_type(type)) {
void do_double() { set(CellTypeState::value); set(CellTypeState::value);
set(CellTypeState::value); } }
void do_long () { set(CellTypeState::value); }
set(CellTypeState::value); } }
public: public:
ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {}; ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {};
@ -194,7 +194,7 @@ public:
if (!is_static) if (!is_static)
effect[_idx++] = CellTypeState::make_slot_ref(0); effect[_idx++] = CellTypeState::make_slot_ref(0);
iterate_parameters(); do_parameters_on(this);
return length(); return length();
}; };
@ -202,7 +202,7 @@ public:
int compute_for_returntype(CellTypeState *effect) { int compute_for_returntype(CellTypeState *effect) {
_idx = 0; _idx = 0;
_effect = effect; _effect = effect;
iterate_returntype(); do_type(return_type(), true);
set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
return length(); return length();
@ -1930,12 +1930,8 @@ void GenerateOopMap::do_field(int is_get, int is_static, int idx, int bci) {
int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
Symbol* signature = cp->symbol_at(signatureIdx); Symbol* signature = cp->symbol_at(signatureIdx);
// Parse signature (espcially simple for fields)
assert(signature->utf8_length() > 0, "field signatures cannot have zero length");
// The signature is UFT8 encoded, but the first char is always ASCII for signatures.
char sigch = (char)*(signature->base());
CellTypeState temp[4]; CellTypeState temp[4];
CellTypeState *eff = sigchar_to_effect(sigch, bci, temp); CellTypeState *eff = signature_to_effect(signature, bci, temp);
CellTypeState in[4]; CellTypeState in[4];
CellTypeState *out; CellTypeState *out;
@ -1991,15 +1987,16 @@ void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci
} }
// This is used to parse the signature for fields, since they are very simple... // This is used to parse the signature for fields, since they are very simple...
CellTypeState *GenerateOopMap::sigchar_to_effect(char sigch, int bci, CellTypeState *out) { CellTypeState *GenerateOopMap::signature_to_effect(const Symbol* sig, int bci, CellTypeState *out) {
// Object and array // Object and array
if (sigch==JVM_SIGNATURE_CLASS || sigch==JVM_SIGNATURE_ARRAY) { BasicType bt = Signature::basic_type(sig);
if (is_reference_type(bt)) {
out[0] = CellTypeState::make_line_ref(bci); out[0] = CellTypeState::make_line_ref(bci);
out[1] = CellTypeState::bottom; out[1] = CellTypeState::bottom;
return out; return out;
} }
if (sigch == JVM_SIGNATURE_LONG || sigch == JVM_SIGNATURE_DOUBLE) return vvCTS; // Long and Double if (is_double_word_type(bt)) return vvCTS; // Long and Double
if (sigch == JVM_SIGNATURE_VOID) return epsilonCTS; // Void if (bt == T_VOID) return epsilonCTS; // Void
return vCTS; // Otherwise return vCTS; // Otherwise
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -403,7 +403,7 @@ class GenerateOopMap {
void do_monitorexit (int bci); void do_monitorexit (int bci);
void do_return_monitor_check (); void do_return_monitor_check ();
void do_checkcast (); void do_checkcast ();
CellTypeState *sigchar_to_effect (char sigch, int bci, CellTypeState *out); CellTypeState *signature_to_effect (const Symbol* sig, int bci, CellTypeState *out);
int copy_cts (CellTypeState *dst, CellTypeState *src); int copy_cts (CellTypeState *dst, CellTypeState *src);
// Error handling // Error handling

View file

@ -577,9 +577,16 @@ int Method::extra_stack_words() {
return extra_stack_entries() * Interpreter::stackElementSize; return extra_stack_entries() * Interpreter::stackElementSize;
} }
void Method::compute_size_of_parameters(Thread *thread) { // Derive size of parameters, return type, and fingerprint,
ArgumentSizeComputer asc(signature()); // all in one pass, which is run at load time.
set_size_of_parameters(asc.size() + (is_static() ? 0 : 1)); // We need the first two, and might as well grab the third.
void Method::compute_from_signature(Symbol* sig) {
// At this point, since we are scanning the signature,
// we might as well compute the whole fingerprint.
Fingerprinter fp(sig, is_static());
set_size_of_parameters(fp.size_of_parameters());
constMethod()->set_result_type(fp.return_type());
constMethod()->set_fingerprint(fp.fingerprint());
} }
bool Method::is_empty_method() const { bool Method::is_empty_method() const {
@ -1443,9 +1450,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
m->set_signature_index(_imcp_invoke_signature); m->set_signature_index(_imcp_invoke_signature);
assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(MethodHandles::is_signature_polymorphic_name(m->name()), "");
assert(m->signature() == signature, ""); assert(m->signature() == signature, "");
ResultTypeFinder rtf(signature); m->compute_from_signature(signature);
m->constMethod()->set_result_type(rtf.type());
m->compute_size_of_parameters(THREAD);
m->init_intrinsic_id(); m->init_intrinsic_id();
assert(m->is_method_handle_intrinsic(), ""); assert(m->is_method_handle_intrinsic(), "");
#ifdef ASSERT #ifdef ASSERT
@ -1685,7 +1690,7 @@ bool Method::load_signature_classes(const methodHandle& m, TRAPS) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
Symbol* signature = m->signature(); Symbol* signature = m->signature();
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) { for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
if (ss.is_object()) { if (ss.is_reference()) {
Symbol* sym = ss.as_symbol(); Symbol* sym = ss.as_symbol();
Symbol* name = sym; Symbol* name = sym;
Klass* klass = SystemDictionary::resolve_or_null(name, class_loader, Klass* klass = SystemDictionary::resolve_or_null(name, class_loader,
@ -1713,8 +1718,7 @@ bool Method::has_unloaded_classes_in_signature(const methodHandle& m, TRAPS) {
Symbol* signature = m->signature(); Symbol* signature = m->signature();
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) { for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
if (ss.type() == T_OBJECT) { if (ss.type() == T_OBJECT) {
Symbol* name = ss.as_symbol_or_null(); Symbol* name = ss.as_symbol();
if (name == NULL) return true;
Klass* klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD); Klass* klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
if (klass == NULL) return true; if (klass == NULL) return true;
} }
@ -1733,7 +1737,7 @@ void Method::print_short_name(outputStream* st) {
name()->print_symbol_on(st); name()->print_symbol_on(st);
if (WizardMode) signature()->print_symbol_on(st); if (WizardMode) signature()->print_symbol_on(st);
else if (MethodHandles::is_signature_polymorphic(intrinsic_id())) else if (MethodHandles::is_signature_polymorphic(intrinsic_id()))
MethodHandles::print_as_basic_type_signature_on(st, signature(), true); MethodHandles::print_as_basic_type_signature_on(st, signature());
} }
// Comparer for sorting an object array containing // Comparer for sorting an object array containing
@ -1786,8 +1790,8 @@ class SignatureTypePrinter : public SignatureTypeNames {
_use_separator = false; _use_separator = false;
} }
void print_parameters() { _use_separator = false; iterate_parameters(); } void print_parameters() { _use_separator = false; do_parameters_on(this); }
void print_returntype() { _use_separator = false; iterate_returntype(); } void print_returntype() { _use_separator = false; do_type(return_type()); }
}; };

View file

@ -307,7 +307,10 @@ class Method : public Metadata {
} }
} }
// size of parameters // Derive stuff from the signature at load time.
void compute_from_signature(Symbol* sig);
// size of parameters (receiver if any + arguments)
int size_of_parameters() const { return constMethod()->size_of_parameters(); } int size_of_parameters() const { return constMethod()->size_of_parameters(); }
void set_size_of_parameters(int size) { constMethod()->set_size_of_parameters(size); } void set_size_of_parameters(int size) { constMethod()->set_size_of_parameters(size); }
@ -605,7 +608,6 @@ public:
// method holder (the Klass* holding this method) // method holder (the Klass* holding this method)
InstanceKlass* method_holder() const { return constants()->pool_holder(); } InstanceKlass* method_holder() const { return constants()->pool_holder(); }
void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments)
Symbol* klass_name() const; // returns the name of the method holder Symbol* klass_name() const; // returns the name of the method holder
BasicType result_type() const { return constMethod()->result_type(); } BasicType result_type() const { return constMethod()->result_type(); }
bool is_returning_oop() const { BasicType r = result_type(); return is_reference_type(r); } bool is_returning_oop() const { BasicType r = result_type(); return is_reference_type(r); }

View file

@ -199,8 +199,8 @@ int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_rec
// Parameter profiling include the receiver // Parameter profiling include the receiver
int args_count = include_receiver ? 1 : 0; int args_count = include_receiver ? 1 : 0;
ResourceMark rm; ResourceMark rm;
SignatureStream ss(signature); ReferenceArgumentCount rac(signature);
args_count += ss.reference_parameter_count(); args_count += rac.count();
args_count = MIN2(args_count, max); args_count = MIN2(args_count, max);
return args_count * per_arg_cell_count; return args_count * per_arg_cell_count;
} }
@ -227,32 +227,28 @@ int TypeEntriesAtCall::compute_cell_count(BytecodeStream* stream) {
return header_cell + args_cell + ret_cell; return header_cell + args_cell + ret_cell;
} }
class ArgumentOffsetComputer : public SignatureInfo { class ArgumentOffsetComputer : public SignatureIterator {
private: private:
int _max; int _max;
int _offset;
GrowableArray<int> _offsets; GrowableArray<int> _offsets;
void set(int size, BasicType type) { _size += size; } friend class SignatureIterator; // so do_parameters_on can call do_type
void do_object(int begin, int end) { void do_type(BasicType type) {
if (_offsets.length() < _max) { if (is_reference_type(type) && _offsets.length() < _max) {
_offsets.push(_size); _offsets.push(_offset);
} }
SignatureInfo::do_object(begin, end); _offset += parameter_type_word_count(type);
}
void do_array (int begin, int end) {
if (_offsets.length() < _max) {
_offsets.push(_size);
}
SignatureInfo::do_array(begin, end);
} }
public: public:
ArgumentOffsetComputer(Symbol* signature, int max) ArgumentOffsetComputer(Symbol* signature, int max)
: SignatureInfo(signature), _max(max), _offsets(Thread::current(), max) { : SignatureIterator(signature),
_max(max), _offset(0),
_offsets(Thread::current(), max) {
do_parameters_on(this); // non-virtual template execution
} }
int total() { lazy_iterate_parameters(); return _size; }
int off_at(int i) const { return _offsets.at(i); } int off_at(int i) const { return _offsets.at(i); }
}; };
@ -266,7 +262,6 @@ void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver,
start += 1; start += 1;
} }
ArgumentOffsetComputer aos(signature, _number_of_entries-start); ArgumentOffsetComputer aos(signature, _number_of_entries-start);
aos.total();
for (int i = start; i < _number_of_entries; i++) { for (int i = start; i < _number_of_entries; i++) {
set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0)); set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
set_type(i, type_none()); set_type(i, type_none());
@ -277,11 +272,11 @@ void CallTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
assert(Bytecodes::is_invoke(stream->code()), "should be invoke"); assert(Bytecodes::is_invoke(stream->code()), "should be invoke");
Bytecode_invoke inv(stream->method(), stream->bci()); Bytecode_invoke inv(stream->method(), stream->bci());
SignatureStream ss(inv.signature());
if (has_arguments()) { if (has_arguments()) {
#ifdef ASSERT #ifdef ASSERT
ResourceMark rm; ResourceMark rm;
int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); ReferenceArgumentCount rac(inv.signature());
int count = MIN2(rac.count(), (int)TypeProfileArgsLimit);
assert(count > 0, "room for args type but none found?"); assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count); check_number_of_arguments(count);
#endif #endif
@ -301,8 +296,8 @@ void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* md
if (has_arguments()) { if (has_arguments()) {
#ifdef ASSERT #ifdef ASSERT
ResourceMark rm; ResourceMark rm;
SignatureStream ss(inv.signature()); ReferenceArgumentCount rac(inv.signature());
int count = MIN2(ss.reference_parameter_count(), (int)TypeProfileArgsLimit); int count = MIN2(rac.count(), (int)TypeProfileArgsLimit);
assert(count > 0, "room for args type but none found?"); assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count); check_number_of_arguments(count);
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -52,6 +52,7 @@ uint32_t Symbol::pack_length_and_refcount(int length, int refcount) {
Symbol::Symbol(const u1* name, int length, int refcount) { Symbol::Symbol(const u1* name, int length, int refcount) {
_length_and_refcount = pack_length_and_refcount(length, refcount); _length_and_refcount = pack_length_and_refcount(length, refcount);
_identity_hash = (short)os::random(); _identity_hash = (short)os::random();
_body[0] = 0; // in case length == 0
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
byte_at_put(i, name[i]); byte_at_put(i, name[i]);
} }
@ -82,20 +83,31 @@ void Symbol::set_permanent() {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// Symbol::starts_with // Symbol::contains_byte_at
// //
// Tests if the symbol starts with the specified prefix of the given // Tests if the symbol contains the given byte at the given position.
// length. bool Symbol::contains_byte_at(int position, char code_byte) const {
bool Symbol::starts_with(const char* prefix, int len) const { if (position < 0) return false; // can happen with ends_with
if (len > utf8_length()) return false; if (position >= utf8_length()) return false;
while (len-- > 0) { return code_byte == char_at(position);
if (prefix[len] != char_at(len))
return false;
}
assert(len == -1, "we should be at the beginning");
return true;
} }
// ------------------------------------------------------------------
// Symbol::contains_utf8_at
//
// Tests if the symbol contains the given utf8 substring
// at the given byte position.
bool Symbol::contains_utf8_at(int position, const char* substring, int len) const {
assert(len >= 0 && substring != NULL, "substring must be valid");
if (len <= 1)
return len == 0 || contains_byte_at(position, substring[0]);
if (position < 0) return false; // can happen with ends_with
if (position + len > utf8_length()) return false;
if (memcmp((char*)base() + position, substring, len) == 0)
return true;
else
return false;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// Symbol::index_of // Symbol::index_of
@ -116,9 +128,12 @@ int Symbol::index_of_at(int i, const char* str, int len) const {
if (scan == NULL) if (scan == NULL)
return -1; // not found return -1; // not found
assert(scan >= bytes+i && scan <= limit, "scan oob"); assert(scan >= bytes+i && scan <= limit, "scan oob");
if (memcmp(scan, str, len) == 0) if (len <= 2
? (char) scan[len-1] == str[len-1]
: memcmp(scan+1, str+1, len-1) == 0) {
return (int)(scan - bytes); return (int)(scan - bytes);
} }
}
return -1; return -1;
} }
@ -186,8 +201,8 @@ const char* Symbol::as_klass_external_name(char* buf, int size) const {
int length = (int)strlen(str); int length = (int)strlen(str);
// Turn all '/'s into '.'s (also for array klasses) // Turn all '/'s into '.'s (also for array klasses)
for (int index = 0; index < length; index++) { for (int index = 0; index < length; index++) {
if (str[index] == '/') { if (str[index] == JVM_SIGNATURE_SLASH) {
str[index] = '.'; str[index] = JVM_SIGNATURE_DOT;
} }
} }
return str; return str;
@ -208,28 +223,25 @@ const char* Symbol::as_klass_external_name() const {
return str; return str;
} }
static void print_class(outputStream *os, char *class_str, int len) { static void print_class(outputStream *os, const SignatureStream& ss) {
for (int i = 0; i < len; ++i) { int sb = ss.raw_symbol_begin(), se = ss.raw_symbol_end();
if (class_str[i] == JVM_SIGNATURE_SLASH) { for (int i = sb; i < se; ++i) {
int ch = ss.raw_char_at(i);
if (ch == JVM_SIGNATURE_SLASH) {
os->put(JVM_SIGNATURE_DOT); os->put(JVM_SIGNATURE_DOT);
} else { } else {
os->put(class_str[i]); os->put(ch);
} }
} }
} }
static void print_array(outputStream *os, char *array_str, int len) { static void print_array(outputStream *os, SignatureStream& ss) {
int dimensions = 0; int dimensions = ss.skip_array_prefix();
for (int i = 0; i < len; ++i) { assert(dimensions > 0, "");
if (array_str[i] == JVM_SIGNATURE_ARRAY) { if (ss.is_reference()) {
dimensions++; print_class(os, ss);
} else if (array_str[i] == JVM_SIGNATURE_CLASS) {
// Expected format: L<type name>;. Skip 'L' and ';' delimiting the type name.
print_class(os, array_str+i+1, len-i-2);
break;
} else { } else {
os->print("%s", type2name(char2type(array_str[i]))); os->print("%s", type2name(ss.type()));
}
} }
for (int i = 0; i < dimensions; ++i) { for (int i = 0; i < dimensions; ++i) {
os->print("[]"); os->print("[]");
@ -240,10 +252,9 @@ void Symbol::print_as_signature_external_return_type(outputStream *os) {
for (SignatureStream ss(this); !ss.is_done(); ss.next()) { for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
if (ss.at_return_type()) { if (ss.at_return_type()) {
if (ss.is_array()) { if (ss.is_array()) {
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length()); print_array(os, ss);
} else if (ss.is_object()) { } else if (ss.is_reference()) {
// Expected format: L<type name>;. Skip 'L' and ';' delimiting the class name. print_class(os, ss);
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
} else { } else {
os->print("%s", type2name(ss.type())); os->print("%s", type2name(ss.type()));
} }
@ -257,10 +268,9 @@ void Symbol::print_as_signature_external_parameters(outputStream *os) {
if (ss.at_return_type()) break; if (ss.at_return_type()) break;
if (!first) { os->print(", "); } if (!first) { os->print(", "); }
if (ss.is_array()) { if (ss.is_array()) {
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length()); print_array(os, ss);
} else if (ss.is_object()) { } else if (ss.is_reference()) {
// Skip 'L' and ';'. print_class(os, ss);
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
} else { } else {
os->print("%s", type2name(ss.type())); os->print("%s", type2name(ss.type()));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -189,20 +189,34 @@ class Symbol : public MetaspaceObj {
bool equals(const char* str, int len) const { bool equals(const char* str, int len) const {
int l = utf8_length(); int l = utf8_length();
if (l != len) return false; if (l != len) return false;
while (l-- > 0) { return contains_utf8_at(0, str, len);
if (str[l] != char_at(l))
return false;
}
assert(l == -1, "we should be at the beginning");
return true;
} }
bool equals(const char* str) const { return equals(str, (int) strlen(str)); } bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
// Tests if the symbol starts with the given prefix. // Tests if the symbol starts with the given prefix.
bool starts_with(const char* prefix, int len) const; bool starts_with(const char* prefix, int len) const {
return contains_utf8_at(0, prefix, len);
}
bool starts_with(const char* prefix) const { bool starts_with(const char* prefix) const {
return starts_with(prefix, (int) strlen(prefix)); return starts_with(prefix, (int) strlen(prefix));
} }
bool starts_with(int prefix_char) const {
return contains_byte_at(0, prefix_char);
}
// Tests if the symbol ends with the given suffix.
bool ends_with(const char* suffix, int len) const {
return contains_utf8_at(utf8_length() - len, suffix, len);
}
bool ends_with(const char* suffix) const {
return ends_with(suffix, (int) strlen(suffix));
}
bool ends_with(int suffix_char) const {
return contains_byte_at(utf8_length()-1, suffix_char);
}
// Tests if the symbol contains the given utf8 substring
// or byte at the given byte position.
bool contains_utf8_at(int position, const char* substring, int len) const;
bool contains_byte_at(int position, char code_byte) const;
// Tests if the symbol starts with the given prefix. // Tests if the symbol starts with the given prefix.
int index_of_at(int i, const char* str, int len) const; int index_of_at(int i, const char* str, int len) const;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Red Hat, Inc. * Copyright (c) 2012 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.
* *
@ -862,40 +862,29 @@ class JNI_ArgumentPusher : public SignatureIterator {
protected: protected:
JavaCallArguments* _arguments; JavaCallArguments* _arguments;
virtual void get_bool () = 0; void push_int(jint x) { _arguments->push_int(x); }
virtual void get_char () = 0; void push_long(jlong x) { _arguments->push_long(x); }
virtual void get_short () = 0; void push_float(jfloat x) { _arguments->push_float(x); }
virtual void get_byte () = 0; void push_double(jdouble x) { _arguments->push_double(x); }
virtual void get_int () = 0; void push_object(jobject x) { _arguments->push_jobject(x); }
virtual void get_long () = 0;
virtual void get_float () = 0;
virtual void get_double () = 0;
virtual void get_object () = 0;
JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) { void push_boolean(jboolean b) {
this->_return_type = T_ILLEGAL; // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and
// 0 to JNI_FALSE. Boolean return values from native are normalized the same in
// TemplateInterpreterGenerator::generate_result_handler_for and
// SharedRuntime::generate_native_wrapper.
push_int(b == 0 ? JNI_FALSE : JNI_TRUE);
}
JNI_ArgumentPusher(Method* method)
: SignatureIterator(method->signature(),
Fingerprinter(methodHandle(Thread::current(), method)).fingerprint())
{
_arguments = NULL; _arguments = NULL;
} }
public: public:
virtual void iterate( uint64_t fingerprint ) = 0; virtual void push_arguments_on(JavaCallArguments* arguments) = 0;
void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; }
inline void do_bool() { if (!is_return_type()) get_bool(); }
inline void do_char() { if (!is_return_type()) get_char(); }
inline void do_short() { if (!is_return_type()) get_short(); }
inline void do_byte() { if (!is_return_type()) get_byte(); }
inline void do_int() { if (!is_return_type()) get_int(); }
inline void do_long() { if (!is_return_type()) get_long(); }
inline void do_float() { if (!is_return_type()) get_float(); }
inline void do_double() { if (!is_return_type()) get_double(); }
inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); }
inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array
inline void do_void() { }
JavaCallArguments* arguments() { return _arguments; }
void push_receiver(Handle h) { _arguments->push_oop(h); }
}; };
@ -903,89 +892,42 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
protected: protected:
va_list _ap; va_list _ap;
inline void get_bool() { void set_ap(va_list rap) {
// Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and
// 0 to JNI_FALSE. Boolean return values from native are normalized the same in
// TemplateInterpreterGenerator::generate_result_handler_for and
// SharedRuntime::generate_native_wrapper.
jboolean b = va_arg(_ap, jint);
_arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));
}
inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg
inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg
inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg
inline void get_int() { _arguments->push_int(va_arg(_ap, jint)); }
// each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }
inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }
inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); }
inline void set_ap(va_list rap) {
va_copy(_ap, rap); va_copy(_ap, rap);
} }
friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) {
switch (type) {
// these are coerced to int when using va_arg
case T_BYTE:
case T_CHAR:
case T_SHORT:
case T_INT: push_int(va_arg(_ap, jint)); break;
case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
// each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
case T_LONG: push_long(va_arg(_ap, jlong)); break;
// float is coerced to double w/ va_arg
case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
case T_ARRAY:
case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
default: ShouldNotReachHere();
}
}
public: public:
JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)
: JNI_ArgumentPusher(signature) {
set_ap(rap);
}
JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap) JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) { : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
set_ap(rap); set_ap(rap);
} }
// Optimized path if we have the bitvector form of signature virtual void push_arguments_on(JavaCallArguments* arguments) {
void iterate( uint64_t fingerprint ) { _arguments = arguments;
if (fingerprint == (uint64_t)CONST64(-1)) { do_parameters_on(this);
SignatureIterator::iterate(); // Must be too many arguments
} else {
_return_type = (BasicType)((fingerprint >> static_feature_size) &
result_feature_mask);
assert(fingerprint, "Fingerprint should not be 0");
fingerprint = fingerprint >> (static_feature_size + result_feature_size);
while ( 1 ) {
switch ( fingerprint & parameter_feature_mask ) {
case bool_parm:
get_bool();
break;
case char_parm:
get_char();
break;
case short_parm:
get_short();
break;
case byte_parm:
get_byte();
break;
case int_parm:
get_int();
break;
case obj_parm:
get_object();
break;
case long_parm:
get_long();
break;
case float_parm:
get_float();
break;
case double_parm:
get_double();
break;
case done_parm:
return;
break;
default:
ShouldNotReachHere();
break;
}
fingerprint >>= parameter_feature_size;
}
}
} }
}; };
@ -994,84 +936,34 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
protected: protected:
const jvalue *_ap; const jvalue *_ap;
inline void get_bool() {
// Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and
// 0 to JNI_FALSE. Boolean return values from native are normalized the same in
// TemplateInterpreterGenerator::generate_result_handler_for and
// SharedRuntime::generate_native_wrapper.
jboolean b = (_ap++)->z;
_arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));
}
inline void get_char() { _arguments->push_int((jint)(_ap++)->c); }
inline void get_short() { _arguments->push_int((jint)(_ap++)->s); }
inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); }
inline void get_int() { _arguments->push_int((jint)(_ap++)->i); }
inline void get_long() { _arguments->push_long((_ap++)->j); }
inline void get_float() { _arguments->push_float((_ap++)->f); }
inline void get_double() { _arguments->push_double((_ap++)->d);}
inline void get_object() { _arguments->push_jobject((_ap++)->l); }
inline void set_ap(const jvalue *rap) { _ap = rap; } inline void set_ap(const jvalue *rap) { _ap = rap; }
public: friend class SignatureIterator; // so do_parameters_on can call do_type
JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap) void do_type(BasicType type) {
: JNI_ArgumentPusher(signature) { switch (type) {
set_ap(rap); case T_CHAR: push_int((_ap++)->c); break;
case T_SHORT: push_int((_ap++)->s); break;
case T_BYTE: push_int((_ap++)->b); break;
case T_INT: push_int((_ap++)->i); break;
case T_BOOLEAN: push_boolean((_ap++)->z); break;
case T_LONG: push_long((_ap++)->j); break;
case T_FLOAT: push_float((_ap++)->f); break;
case T_DOUBLE: push_double((_ap++)->d); break;
case T_ARRAY:
case T_OBJECT: push_object((_ap++)->l); break;
default: ShouldNotReachHere();
} }
}
public:
JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap) JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) { : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
set_ap(rap); set_ap(rap);
} }
// Optimized path if we have the bitvector form of signature virtual void push_arguments_on(JavaCallArguments* arguments) {
void iterate( uint64_t fingerprint ) { _arguments = arguments;
if (fingerprint == (uint64_t)CONST64(-1)) { do_parameters_on(this);
SignatureIterator::iterate(); // Must be too many arguments
} else {
_return_type = (BasicType)((fingerprint >> static_feature_size) &
result_feature_mask);
assert(fingerprint, "Fingerprint should not be 0");
fingerprint = fingerprint >> (static_feature_size + result_feature_size);
while ( 1 ) {
switch ( fingerprint & parameter_feature_mask ) {
case bool_parm:
get_bool();
break;
case char_parm:
get_char();
break;
case short_parm:
get_short();
break;
case byte_parm:
get_byte();
break;
case int_parm:
get_int();
break;
case obj_parm:
get_object();
break;
case long_parm:
get_long();
break;
case float_parm:
get_float();
break;
case double_parm:
get_double();
break;
case done_parm:
return;
break;
default:
ShouldNotReachHere();
break;
}
fingerprint >>= parameter_feature_size;
}
}
} }
}; };
@ -1092,14 +984,13 @@ static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver,
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
int number_of_parameters = method->size_of_parameters(); int number_of_parameters = method->size_of_parameters();
JavaCallArguments java_args(number_of_parameters); JavaCallArguments java_args(number_of_parameters);
args->set_java_argument_object(&java_args);
assert(method->is_static(), "method should be static"); assert(method->is_static(), "method should be static");
// Fill out JavaCallArguments object // Fill out JavaCallArguments object
args->iterate( Fingerprinter(method).fingerprint() ); args->push_arguments_on(&java_args);
// Initialize result type // Initialize result type
result->set_type(args->get_ret_type()); result->set_type(args->return_type());
// Invoke the method. Result is returned as oop. // Invoke the method. Result is returned as oop.
JavaCalls::call(result, method, &java_args, CHECK); JavaCalls::call(result, method, &java_args, CHECK);
@ -1153,16 +1044,15 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
// the jni parser // the jni parser
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
JavaCallArguments java_args(number_of_parameters); JavaCallArguments java_args(number_of_parameters);
args->set_java_argument_object(&java_args);
// handle arguments // handle arguments
assert(!method->is_static(), "method %s should not be static", method->name_and_sig_as_C_string()); assert(!method->is_static(), "method %s should not be static", method->name_and_sig_as_C_string());
args->push_receiver(h_recv); // Push jobject handle java_args.push_oop(h_recv); // Push jobject handle
// Fill out JavaCallArguments object // Fill out JavaCallArguments object
args->iterate( Fingerprinter(method).fingerprint() ); args->push_arguments_on(&java_args);
// Initialize result type // Initialize result type
result->set_type(args->get_ret_type()); result->set_type(args->return_type());
// Invoke the method. Result is returned as oop. // Invoke the method. Result is returned as oop.
JavaCalls::call(result, method, &java_args, CHECK); JavaCalls::call(result, method, &java_args, CHECK);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -570,8 +570,7 @@ bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
return false; // Incorrect slot index return false; // Incorrect slot index
} }
Symbol* sign_sym = method_oop->constants()->symbol_at(signature_idx); Symbol* sign_sym = method_oop->constants()->symbol_at(signature_idx);
const char* signature = (const char *) sign_sym->as_utf8(); BasicType slot_type = Signature::basic_type(sign_sym);
BasicType slot_type = char2type(signature[0]);
switch (slot_type) { switch (slot_type) {
case T_BYTE: case T_BYTE:
@ -602,6 +601,7 @@ bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
Klass* ob_k = obj->klass(); Klass* ob_k = obj->klass();
NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); NULL_CHECK(ob_k, (_result = JVMTI_ERROR_INVALID_OBJECT, false));
const char* signature = (const char *) sign_sym->as_utf8();
if (!is_assignable(signature, ob_k, cur_thread)) { if (!is_assignable(signature, ob_k, cur_thread)) {
_result = JVMTI_ERROR_TYPE_MISMATCH; _result = JVMTI_ERROR_TYPE_MISMATCH;
return false; return false;

View file

@ -539,25 +539,21 @@ enum { OBJ_SIG_LEN = 18 };
bool MethodHandles::is_basic_type_signature(Symbol* sig) { bool MethodHandles::is_basic_type_signature(Symbol* sig) {
assert(vmSymbols::object_signature()->utf8_length() == (int)OBJ_SIG_LEN, ""); assert(vmSymbols::object_signature()->utf8_length() == (int)OBJ_SIG_LEN, "");
assert(vmSymbols::object_signature()->equals(OBJ_SIG), ""); assert(vmSymbols::object_signature()->equals(OBJ_SIG), "");
const int len = sig->utf8_length(); for (SignatureStream ss(sig, sig->starts_with(JVM_SIGNATURE_FUNC)); !ss.is_done(); ss.next()) {
for (int i = 0; i < len; i++) { switch (ss.type()) {
switch (sig->char_at(i)) { case T_OBJECT:
case JVM_SIGNATURE_CLASS:
// only java/lang/Object is valid here // only java/lang/Object is valid here
if (sig->index_of_at(i, OBJ_SIG, OBJ_SIG_LEN) != i) if (strncmp((char*) ss.raw_bytes(), OBJ_SIG, OBJ_SIG_LEN) != 0)
return false; return false;
i += OBJ_SIG_LEN-1; //-1 because of i++ in loop break;
continue; case T_VOID:
case JVM_SIGNATURE_FUNC: case T_INT:
case JVM_SIGNATURE_ENDFUNC: case T_LONG:
case JVM_SIGNATURE_VOID: case T_FLOAT:
case JVM_SIGNATURE_INT: case T_DOUBLE:
case JVM_SIGNATURE_LONG: break;
case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_DOUBLE:
continue;
default: default:
// subword types (T_BYTE etc.), arrays // subword types (T_BYTE etc.), Q-descriptors, arrays
return false; return false;
} }
} }
@ -571,8 +567,8 @@ Symbol* MethodHandles::lookup_basic_type_signature(Symbol* sig, bool keep_last_a
} else if (is_basic_type_signature(sig)) { } else if (is_basic_type_signature(sig)) {
sig->increment_refcount(); sig->increment_refcount();
return sig; // that was easy return sig; // that was easy
} else if (sig->char_at(0) != JVM_SIGNATURE_FUNC) { } else if (!sig->starts_with(JVM_SIGNATURE_FUNC)) {
BasicType bt = char2type(sig->char_at(0)); BasicType bt = Signature::basic_type(sig);
if (is_subword_type(bt)) { if (is_subword_type(bt)) {
bsig = vmSymbols::int_signature(); bsig = vmSymbols::int_signature();
} else { } else {
@ -615,71 +611,26 @@ Symbol* MethodHandles::lookup_basic_type_signature(Symbol* sig, bool keep_last_a
} }
void MethodHandles::print_as_basic_type_signature_on(outputStream* st, void MethodHandles::print_as_basic_type_signature_on(outputStream* st,
Symbol* sig, Symbol* sig) {
bool keep_arrays,
bool keep_basic_names) {
st = st ? st : tty; st = st ? st : tty;
int len = sig->utf8_length();
int array = 0;
bool prev_type = false; bool prev_type = false;
for (int i = 0; i < len; i++) { bool is_method = (sig->char_at(0) == JVM_SIGNATURE_FUNC);
char ch = sig->char_at(i); if (is_method) st->put(JVM_SIGNATURE_FUNC);
switch (ch) { for (SignatureStream ss(sig, is_method); !ss.is_done(); ss.next()) {
case JVM_SIGNATURE_FUNC: if (ss.at_return_type())
case JVM_SIGNATURE_ENDFUNC: st->put(JVM_SIGNATURE_ENDFUNC);
prev_type = false; else if (prev_type)
st->put(ch); st->put(',');
continue; const char* cp = (const char*) ss.raw_bytes();
case JVM_SIGNATURE_ARRAY: if (ss.is_array()) {
if (!keep_basic_names && keep_arrays) st->put(JVM_SIGNATURE_ARRAY);
st->put(ch); if (ss.array_prefix_length() == 1)
array++; st->put(cp[1]);
continue; else
case JVM_SIGNATURE_CLASS:
{
if (prev_type) st->put(',');
int start = i+1, slash = start;
while (++i < len && (ch = sig->char_at(i)) != JVM_SIGNATURE_ENDCLASS) {
if (ch == JVM_SIGNATURE_SLASH || ch == JVM_SIGNATURE_DOT || ch == '$') slash = i+1;
}
if (slash < i) start = slash;
if (!keep_basic_names) {
st->put(JVM_SIGNATURE_CLASS); st->put(JVM_SIGNATURE_CLASS);
} else { } else {
for (int j = start; j < i; j++) st->put(cp[0]);
st->put(sig->char_at(j));
prev_type = true;
} }
break;
}
default:
{
if (array && char2type(ch) != T_ILLEGAL && !keep_arrays) {
ch = JVM_SIGNATURE_ARRAY;
array = 0;
}
if (prev_type) st->put(',');
const char* n = NULL;
if (keep_basic_names)
n = type2name(char2type(ch));
if (n == NULL) {
// unknown letter, or we don't want to know its name
st->put(ch);
} else {
st->print("%s", n);
prev_type = true;
}
break;
}
}
// Switch break goes here to take care of array suffix:
if (prev_type) {
while (array > 0) {
st->print("[]");
--array;
}
}
array = 0;
} }
} }
@ -696,7 +647,7 @@ oop MethodHandles::field_name_or_null(Symbol* s) {
oop MethodHandles::field_signature_type_or_null(Symbol* s) { oop MethodHandles::field_signature_type_or_null(Symbol* s) {
if (s == NULL) return NULL; if (s == NULL) return NULL;
BasicType bt = FieldType::basic_type(s); BasicType bt = Signature::basic_type(s);
if (is_java_primitive(bt)) { if (is_java_primitive(bt)) {
assert(s->utf8_length() == 1, ""); assert(s->utf8_length() == 1, "");
return java_lang_Class::primitive_mirror(bt); return java_lang_Class::primitive_mirror(bt);
@ -982,8 +933,7 @@ int MethodHandles::find_MemberNames(Klass* k,
if (name->utf8_length() == 0) return 0; // a match is not possible if (name->utf8_length() == 0) return 0; // a match is not possible
} }
if (sig != NULL) { if (sig != NULL) {
if (sig->utf8_length() == 0) return 0; // a match is not possible if (sig->starts_with(JVM_SIGNATURE_FUNC))
if (sig->char_at(0) == JVM_SIGNATURE_FUNC)
match_flags &= ~(IS_FIELD | IS_TYPE); match_flags &= ~(IS_FIELD | IS_TYPE);
else else
match_flags &= ~(IS_CONSTRUCTOR | IS_METHOD); match_flags &= ~(IS_CONSTRUCTOR | IS_METHOD);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -155,7 +155,7 @@ public:
} }
static bool is_basic_type_signature(Symbol* sig); static bool is_basic_type_signature(Symbol* sig);
static void print_as_basic_type_signature_on(outputStream* st, Symbol* sig, bool keep_arrays = false, bool keep_basic_names = false); static void print_as_basic_type_signature_on(outputStream* st, Symbol* sig);
// decoding CONSTANT_MethodHandle constants // decoding CONSTANT_MethodHandle constants
enum { JVM_REF_MIN = JVM_REF_getField, JVM_REF_MAX = JVM_REF_invokeInterface }; enum { JVM_REF_MIN = JVM_REF_getField, JVM_REF_MAX = JVM_REF_invokeInterface };

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -1165,7 +1165,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) { if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
ReassignedField field; ReassignedField field;
field._offset = fs.offset(); field._offset = fs.offset();
field._type = FieldType::basic_type(fs.signature()); field._type = Signature::basic_type(fs.signature());
fields->append(field); fields->append(field);
} }
} }
@ -1606,33 +1606,20 @@ Deoptimization::get_method_data(JavaThread* thread, const methodHandle& m,
#if COMPILER2_OR_JVMCI #if COMPILER2_OR_JVMCI
void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) { void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) {
// in case of an unresolved klass entry, load the class. // In case of an unresolved klass entry, load the class.
// This path is exercised from case _ldc in Parse::do_one_bytecode,
// and probably nowhere else.
// Even that case would benefit from simply re-interpreting the
// bytecode, without paying special attention to the class index.
// So this whole "class index" feature should probably be removed.
if (constant_pool->tag_at(index).is_unresolved_klass()) { if (constant_pool->tag_at(index).is_unresolved_klass()) {
Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK); Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK);
return; return;
} }
if (!constant_pool->tag_at(index).is_symbol()) return; assert(!constant_pool->tag_at(index).is_symbol(),
"no symbolic names here, please");
Handle class_loader (THREAD, constant_pool->pool_holder()->class_loader());
Symbol* symbol = constant_pool->symbol_at(index);
// class name?
if (symbol->char_at(0) != '(') {
Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain());
SystemDictionary::resolve_or_null(symbol, class_loader, protection_domain, CHECK);
return;
}
// then it must be a signature!
ResourceMark rm(THREAD);
for (SignatureStream ss(symbol); !ss.is_done(); ss.next()) {
if (ss.is_object()) {
Symbol* class_name = ss.as_symbol();
Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain());
SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK);
}
}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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,7 +29,6 @@
#include "oops/fieldInfo.hpp" #include "oops/fieldInfo.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/symbol.hpp" #include "oops/symbol.hpp"
#include "runtime/fieldType.hpp"
#include "utilities/accessFlags.hpp" #include "utilities/accessFlags.hpp"
#include "utilities/constantTag.hpp" #include "utilities/constantTag.hpp"

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -76,7 +76,7 @@ inline void fieldDescriptor::set_has_initialized_final_update(const bool value)
} }
inline BasicType fieldDescriptor::field_type() const { inline BasicType fieldDescriptor::field_type() const {
return FieldType::basic_type(signature()); return Signature::basic_type(signature());
} }
#endif // SHARE_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP #endif // SHARE_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -714,15 +714,16 @@ class InterpreterFrameClosure : public OffsetClosure {
}; };
class InterpretedArgumentOopFinder: public SignatureInfo { class InterpretedArgumentOopFinder: public SignatureIterator {
private: private:
OopClosure* _f; // Closure to invoke OopClosure* _f; // Closure to invoke
int _offset; // TOS-relative offset, decremented with each argument int _offset; // TOS-relative offset, decremented with each argument
bool _has_receiver; // true if the callee has a receiver bool _has_receiver; // true if the callee has a receiver
frame* _fr; frame* _fr;
void set(int size, BasicType type) { friend class SignatureIterator; // so do_parameters_on can call do_type
_offset -= size; void do_type(BasicType type) {
_offset -= parameter_type_word_count(type);
if (is_reference_type(type)) oop_offset_do(); if (is_reference_type(type)) oop_offset_do();
} }
@ -733,7 +734,7 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
} }
public: public:
InterpretedArgumentOopFinder(Symbol* signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureInfo(signature), _has_receiver(has_receiver) { InterpretedArgumentOopFinder(Symbol* signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureIterator(signature), _has_receiver(has_receiver) {
// compute size of arguments // compute size of arguments
int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0); int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0);
assert(!fr->is_interpreted_frame() || assert(!fr->is_interpreted_frame() ||
@ -750,7 +751,7 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
--_offset; --_offset;
oop_offset_do(); oop_offset_do();
} }
iterate_parameters(); do_parameters_on(this);
} }
}; };
@ -767,17 +768,19 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
// visits and GC's all the arguments in entry frame // visits and GC's all the arguments in entry frame
class EntryFrameOopFinder: public SignatureInfo { class EntryFrameOopFinder: public SignatureIterator {
private: private:
bool _is_static; bool _is_static;
int _offset; int _offset;
frame* _fr; frame* _fr;
OopClosure* _f; OopClosure* _f;
void set(int size, BasicType type) { friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) {
// decrement offset before processing the type
_offset -= parameter_type_word_count(type);
assert (_offset >= 0, "illegal offset"); assert (_offset >= 0, "illegal offset");
if (is_reference_type(type)) oop_at_offset_do(_offset); if (is_reference_type(type)) oop_at_offset_do(_offset);
_offset -= size;
} }
void oop_at_offset_do(int offset) { void oop_at_offset_do(int offset) {
@ -787,17 +790,17 @@ class EntryFrameOopFinder: public SignatureInfo {
} }
public: public:
EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureInfo(signature) { EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureIterator(signature) {
_f = NULL; // will be set later _f = NULL; // will be set later
_fr = frame; _fr = frame;
_is_static = is_static; _is_static = is_static;
_offset = ArgumentSizeComputer(signature).size() - 1; // last parameter is at index 0 _offset = ArgumentSizeComputer(signature).size(); // pre-decremented down to zero
} }
void arguments_do(OopClosure* f) { void arguments_do(OopClosure* f) {
_f = f; _f = f;
if (!_is_static) oop_at_offset_do(_offset+1); // do the receiver if (!_is_static) oop_at_offset_do(_offset); // do the receiver
iterate_parameters(); do_parameters_on(this);
} }
}; };
@ -915,7 +918,7 @@ void frame::oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const Register
cf->do_code_blob(_cb); cf->do_code_blob(_cb);
} }
class CompiledArgumentOopFinder: public SignatureInfo { class CompiledArgumentOopFinder: public SignatureIterator {
protected: protected:
OopClosure* _f; OopClosure* _f;
int _offset; // the current offset, incremented with each argument int _offset; // the current offset, incremented with each argument
@ -926,9 +929,10 @@ class CompiledArgumentOopFinder: public SignatureInfo {
int _arg_size; int _arg_size;
VMRegPair* _regs; // VMReg list of arguments VMRegPair* _regs; // VMReg list of arguments
void set(int size, BasicType type) { friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) {
if (is_reference_type(type)) handle_oop_offset(); if (is_reference_type(type)) handle_oop_offset();
_offset += size; _offset += parameter_type_word_count(type);
} }
virtual void handle_oop_offset() { virtual void handle_oop_offset() {
@ -941,7 +945,7 @@ class CompiledArgumentOopFinder: public SignatureInfo {
public: public:
CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map) CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map)
: SignatureInfo(signature) { : SignatureIterator(signature) {
// initialize CompiledArgumentOopFinder // initialize CompiledArgumentOopFinder
_f = f; _f = f;
@ -962,7 +966,7 @@ class CompiledArgumentOopFinder: public SignatureInfo {
handle_oop_offset(); handle_oop_offset();
_offset++; _offset++;
} }
iterate_parameters(); do_parameters_on(this);
if (_has_appendix) { if (_has_appendix) {
handle_oop_offset(); handle_oop_offset();
_offset++; _offset++;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -521,8 +521,6 @@ class SignatureChekker : public SignatureIterator {
intptr_t* _value; intptr_t* _value;
public: public:
bool _is_return;
SignatureChekker(Symbol* signature, SignatureChekker(Symbol* signature,
BasicType return_type, BasicType return_type,
bool is_static, bool is_static,
@ -532,17 +530,19 @@ class SignatureChekker : public SignatureIterator {
_pos(0), _pos(0),
_return_type(return_type), _return_type(return_type),
_value_state(value_state), _value_state(value_state),
_value(value), _value(value)
_is_return(false)
{ {
if (!is_static) { if (!is_static) {
check_value(true); // Receiver must be an oop check_value(true); // Receiver must be an oop
} }
do_parameters_on(this);
check_return_type(return_type);
} }
void check_value(bool type) { private:
void check_value(bool is_reference) {
uint state = _value_state[_pos++]; uint state = _value_state[_pos++];
if (type) { if (is_reference) {
guarantee(is_value_state_indirect_oop(state), guarantee(is_value_state_indirect_oop(state),
"signature does not match pushed arguments: %u at %d", "signature does not match pushed arguments: %u at %d",
state, _pos - 1); state, _pos - 1);
@ -553,38 +553,20 @@ class SignatureChekker : public SignatureIterator {
} }
} }
void check_doing_return(bool state) { _is_return = state; }
void check_return_type(BasicType t) { void check_return_type(BasicType t) {
guarantee(_is_return && t == _return_type, "return type does not match"); guarantee(t == _return_type, "return type does not match");
} }
void check_int(BasicType t) { void check_single_word() {
if (_is_return) {
check_return_type(t);
return;
}
check_value(false); check_value(false);
} }
void check_double(BasicType t) { check_long(t); } void check_double_word() {
void check_long(BasicType t) {
if (_is_return) {
check_return_type(t);
return;
}
check_value(false); check_value(false);
check_value(false); check_value(false);
} }
void check_obj(BasicType t) { void check_reference() {
if (_is_return) {
check_return_type(t);
return;
}
intptr_t v = _value[_pos]; intptr_t v = _value[_pos];
if (v != 0) { if (v != 0) {
// v is a "handle" referring to an oop, cast to integral type. // v is a "handle" referring to an oop, cast to integral type.
@ -601,17 +583,26 @@ class SignatureChekker : public SignatureIterator {
check_value(true); // Verify value state. check_value(true); // Verify value state.
} }
void do_bool() { check_int(T_BOOLEAN); } friend class SignatureIterator; // so do_parameters_on can call do_type
void do_char() { check_int(T_CHAR); } void do_type(BasicType type) {
void do_float() { check_int(T_FLOAT); } switch (type) {
void do_double() { check_double(T_DOUBLE); } case T_BYTE:
void do_byte() { check_int(T_BYTE); } case T_BOOLEAN:
void do_short() { check_int(T_SHORT); } case T_CHAR:
void do_int() { check_int(T_INT); } case T_SHORT:
void do_long() { check_long(T_LONG); } case T_INT:
void do_void() { check_return_type(T_VOID); } case T_FLOAT: // this one also
void do_object(int begin, int end) { check_obj(T_OBJECT); } check_single_word(); break;
void do_array(int begin, int end) { check_obj(T_OBJECT); } case T_LONG:
case T_DOUBLE:
check_double_word(); break;
case T_ARRAY:
case T_OBJECT:
check_reference(); break;
default:
ShouldNotReachHere();
}
}
}; };
@ -629,7 +620,4 @@ void JavaCallArguments::verify(const methodHandle& method, BasicType return_type
method->is_static(), method->is_static(),
_value_state, _value_state,
_value); _value);
sc.iterate_parameters();
sc.check_doing_return(true);
sc.iterate_returntype();
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -808,8 +808,9 @@ static objArrayHandle get_exception_types(const methodHandle& method, TRAPS) {
} }
static Handle new_type(Symbol* signature, Klass* k, TRAPS) { static Handle new_type(Symbol* signature, Klass* k, TRAPS) {
SignatureStream ss(signature, false);
// Basic types // Basic types
BasicType type = vmSymbols::signature_type(signature); BasicType type = ss.is_reference() ? T_OBJECT : ss.type();
if (type != T_OBJECT) { if (type != T_OBJECT) {
return Handle(THREAD, Universe::java_mirror(type)); return Handle(THREAD, Universe::java_mirror(type));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -2979,9 +2979,6 @@ VMReg SharedRuntime::name_for_receiver() {
VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, bool has_appendix, int* arg_size) { VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, bool has_appendix, int* arg_size) {
// This method is returning a data structure allocating as a // This method is returning a data structure allocating as a
// ResourceObject, so do not put any ResourceMarks in here. // ResourceObject, so do not put any ResourceMarks in here.
char *s = sig->as_C_string();
int len = (int)strlen(s);
s++; len--; // Skip opening paren
BasicType *sig_bt = NEW_RESOURCE_ARRAY(BasicType, 256); BasicType *sig_bt = NEW_RESOURCE_ARRAY(BasicType, 256);
VMRegPair *regs = NEW_RESOURCE_ARRAY(VMRegPair, 256); VMRegPair *regs = NEW_RESOURCE_ARRAY(VMRegPair, 256);
@ -2990,33 +2987,11 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver,
sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature
} }
while (*s != JVM_SIGNATURE_ENDFUNC) { // Find closing right paren for (SignatureStream ss(sig); !ss.at_return_type(); ss.next()) {
switch (*s++) { // Switch on signature character BasicType type = ss.type();
case JVM_SIGNATURE_BYTE: sig_bt[cnt++] = T_BYTE; break; sig_bt[cnt++] = type;
case JVM_SIGNATURE_CHAR: sig_bt[cnt++] = T_CHAR; break; if (is_double_word_type(type))
case JVM_SIGNATURE_DOUBLE: sig_bt[cnt++] = T_DOUBLE; sig_bt[cnt++] = T_VOID; break; sig_bt[cnt++] = T_VOID;
case JVM_SIGNATURE_FLOAT: sig_bt[cnt++] = T_FLOAT; break;
case JVM_SIGNATURE_INT: sig_bt[cnt++] = T_INT; break;
case JVM_SIGNATURE_LONG: sig_bt[cnt++] = T_LONG; sig_bt[cnt++] = T_VOID; break;
case JVM_SIGNATURE_SHORT: sig_bt[cnt++] = T_SHORT; break;
case JVM_SIGNATURE_BOOLEAN: sig_bt[cnt++] = T_BOOLEAN; break;
case JVM_SIGNATURE_VOID: sig_bt[cnt++] = T_VOID; break;
case JVM_SIGNATURE_CLASS: // Oop
while (*s++ != JVM_SIGNATURE_ENDCLASS); // Skip signature
sig_bt[cnt++] = T_OBJECT;
break;
case JVM_SIGNATURE_ARRAY: { // Array
do { // Skip optional size
while (*s >= '0' && *s <= '9') s++;
} while (*s++ == JVM_SIGNATURE_ARRAY); // Nested arrays?
// Skip element type
if (s[-1] == JVM_SIGNATURE_CLASS)
while (*s++ != JVM_SIGNATURE_ENDCLASS); // Skip signature
sig_bt[cnt++] = T_ARRAY;
break;
}
default : ShouldNotReachHere();
}
} }
if (has_appendix) { if (has_appendix) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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
@ -32,6 +32,9 @@
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/symbol.hpp" #include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp" #include "oops/typeArrayKlass.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "runtime/signature.hpp" #include "runtime/signature.hpp"
// Implementation of SignatureIterator // Implementation of SignatureIterator
@ -44,232 +47,154 @@
// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType. // FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
// ClassName = string. // ClassName = string.
// The ClassName string can be any JVM-style UTF8 string except:
// - an empty string (the empty string is never a name of any kind)
// - a string which begins or ends with slash '/' (the package separator)
// - a string which contains adjacent slashes '//' (no empty package names)
// - a string which contains a semicolon ';' (the end-delimiter)
// - a string which contains a left bracket '[' (the array marker)
// - a string which contains a dot '.' (the external package separator)
//
// Other "meta-looking" characters, such as '(' and '<' and '+',
// are perfectly legitimate within a class name, for the JVM.
// Class names which contain double slashes ('a//b') and non-initial
// brackets ('a[b]') are reserved for possible enrichment of the
// type language.
SignatureIterator::SignatureIterator(Symbol* signature) { void SignatureIterator::set_fingerprint(fingerprint_t fingerprint) {
_signature = signature; if (!fp_is_valid(fingerprint)) {
_parameter_index = 0; _fingerprint = fingerprint;
} _return_type = T_ILLEGAL;
} else if (fingerprint != _fingerprint) {
void SignatureIterator::expect(char c) { assert(_fingerprint == zero_fingerprint(), "consistent fingerprint values");
if (_signature->char_at(_index) != c) fatal("expecting %c", c); _fingerprint = fingerprint;
_index++; _return_type = fp_return_type(fingerprint);
}
int SignatureIterator::parse_type() {
// Note: This function could be simplified by using "return T_XXX_size;"
// instead of the assignment and the break statements. However, it
// seems that the product build for win32_i486 with MS VC++ 6.0 doesn't
// work (stack underflow for some tests) - this seems to be a VC++ 6.0
// compiler bug (was problem - gri 4/27/2000).
int size = -1;
switch(_signature->char_at(_index)) {
case JVM_SIGNATURE_BYTE: do_byte(); if (_parameter_index < 0 ) _return_type = T_BYTE;
_index++; size = T_BYTE_size; break;
case JVM_SIGNATURE_CHAR: do_char(); if (_parameter_index < 0 ) _return_type = T_CHAR;
_index++; size = T_CHAR_size; break;
case JVM_SIGNATURE_DOUBLE: do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE;
_index++; size = T_DOUBLE_size; break;
case JVM_SIGNATURE_FLOAT: do_float(); if (_parameter_index < 0 ) _return_type = T_FLOAT;
_index++; size = T_FLOAT_size; break;
case JVM_SIGNATURE_INT: do_int(); if (_parameter_index < 0 ) _return_type = T_INT;
_index++; size = T_INT_size; break;
case JVM_SIGNATURE_LONG: do_long(); if (_parameter_index < 0 ) _return_type = T_LONG;
_index++; size = T_LONG_size; break;
case JVM_SIGNATURE_SHORT: do_short(); if (_parameter_index < 0 ) _return_type = T_SHORT;
_index++; size = T_SHORT_size; break;
case JVM_SIGNATURE_BOOLEAN: do_bool(); if (_parameter_index < 0 ) _return_type = T_BOOLEAN;
_index++; size = T_BOOLEAN_size; break;
case JVM_SIGNATURE_VOID: do_void(); if (_parameter_index < 0 ) _return_type = T_VOID;
_index++; size = T_VOID_size; break;
case JVM_SIGNATURE_CLASS:
{ int begin = ++_index;
Symbol* sig = _signature;
while (sig->char_at(_index++) != JVM_SIGNATURE_ENDCLASS) ;
do_object(begin, _index);
}
if (_parameter_index < 0 ) _return_type = T_OBJECT;
size = T_OBJECT_size;
break;
case JVM_SIGNATURE_ARRAY:
{ int begin = ++_index;
Symbol* sig = _signature;
while (sig->char_at(_index) == JVM_SIGNATURE_ARRAY) {
_index++;
}
if (sig->char_at(_index) == JVM_SIGNATURE_CLASS) {
while (sig->char_at(_index++) != JVM_SIGNATURE_ENDCLASS) ;
} else {
_index++;
}
do_array(begin, _index);
if (_parameter_index < 0 ) _return_type = T_ARRAY;
}
size = T_ARRAY_size;
break;
default:
ShouldNotReachHere();
break;
}
assert(size >= 0, "size must be set");
return size;
}
void SignatureIterator::check_signature_end() {
if (_index < _signature->utf8_length()) {
tty->print_cr("too many chars in signature");
_signature->print_value_on(tty);
tty->print_cr(" @ %d", _index);
} }
} }
BasicType SignatureIterator::return_type() {
void SignatureIterator::iterate_parameters() { if (_return_type == T_ILLEGAL) {
// Parse parameters SignatureStream ss(_signature);
_index = 0; ss.skip_to_return_type();
_parameter_index = 0; _return_type = ss.type();
expect(JVM_SIGNATURE_FUNC); assert(_return_type != T_ILLEGAL, "illegal return type");
while (_signature->char_at(_index) != JVM_SIGNATURE_ENDFUNC) _parameter_index += parse_type(); }
expect(JVM_SIGNATURE_ENDFUNC); return _return_type;
_parameter_index = 0;
} }
// Optimized version of iterate_parameters when fingerprint is known bool SignatureIterator::fp_is_valid_type(BasicType type, bool for_return_type) {
void SignatureIterator::iterate_parameters( uint64_t fingerprint ) { assert(type != (BasicType)fp_parameters_done, "fingerprint is incorrectly at done");
uint64_t saved_fingerprint = fingerprint; assert(((int)type & ~fp_parameter_feature_mask) == 0, "fingerprint feature mask yielded non-zero value");
return (is_java_primitive(type) ||
is_reference_type(type) ||
(for_return_type && type == T_VOID));
}
// Check for too many arguments ArgumentSizeComputer::ArgumentSizeComputer(Symbol* signature)
if (fingerprint == (uint64_t)CONST64(-1)) { : SignatureIterator(signature)
SignatureIterator::iterate_parameters(); {
_size = 0;
do_parameters_on(this); // non-virtual template execution
}
ArgumentCount::ArgumentCount(Symbol* signature)
: SignatureIterator(signature)
{
_size = 0;
do_parameters_on(this); // non-virtual template execution
}
ReferenceArgumentCount::ReferenceArgumentCount(Symbol* signature)
: SignatureIterator(signature)
{
_refs = 0;
do_parameters_on(this); // non-virtual template execution
}
void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) {
// See if we fingerprinted this method already
if (_method != NULL) {
assert(!static_flag, "must not be passed by caller");
static_flag = _method->is_static();
_fingerprint = _method->constMethod()->fingerprint();
if (_fingerprint != zero_fingerprint()) {
_return_type = _method->result_type();
assert(is_java_type(_return_type), "return type must be a java type");
return; return;
} }
assert(fingerprint, "Fingerprint should not be 0"); if (_method->size_of_parameters() > fp_max_size_of_parameters) {
_fingerprint = overflow_fingerprint();
_parameter_index = 0; _method->constMethod()->set_fingerprint(_fingerprint);
fingerprint = fingerprint >> (static_feature_size + result_feature_size); // as long as we are here compute the return type:
while ( 1 ) { _return_type = ResultTypeFinder(_method->signature()).type();
switch ( fingerprint & parameter_feature_mask ) { assert(is_java_type(_return_type), "return type must be a java type");
case bool_parm:
do_bool();
_parameter_index += T_BOOLEAN_size;
break;
case byte_parm:
do_byte();
_parameter_index += T_BYTE_size;
break;
case char_parm:
do_char();
_parameter_index += T_CHAR_size;
break;
case short_parm:
do_short();
_parameter_index += T_SHORT_size;
break;
case int_parm:
do_int();
_parameter_index += T_INT_size;
break;
case obj_parm:
do_object(0, 0);
_parameter_index += T_OBJECT_size;
break;
case long_parm:
do_long();
_parameter_index += T_LONG_size;
break;
case float_parm:
do_float();
_parameter_index += T_FLOAT_size;
break;
case double_parm:
do_double();
_parameter_index += T_DOUBLE_size;
break;
case done_parm:
return; return;
default:
tty->print_cr("*** parameter is " UINT64_FORMAT, fingerprint & parameter_feature_mask);
tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint);
ShouldNotReachHere();
break;
}
fingerprint >>= parameter_feature_size;
} }
} }
// Note: This will always take the slow path, since _fp==zero_fp.
initialize_accumulator();
do_parameters_on(this);
assert(fp_is_valid_type(_return_type, true), "bad result type");
void SignatureIterator::iterate_returntype() { // Fill in the return type and static bits:
// Ignore parameters _accumulator |= _return_type << fp_static_feature_size;
_index = 0; if (static_flag) {
expect(JVM_SIGNATURE_FUNC); _accumulator |= fp_is_static_bit;
Symbol* sig = _signature;
// Need to skip over each type in the signature's argument list until a
// closing ')' is found., then get the return type. We cannot just scan
// for the first ')' because ')' is a legal character in a type name.
while (sig->char_at(_index) != JVM_SIGNATURE_ENDFUNC) {
switch(sig->char_at(_index)) {
case JVM_SIGNATURE_BYTE:
case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_DOUBLE:
case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_LONG:
case JVM_SIGNATURE_SHORT:
case JVM_SIGNATURE_BOOLEAN:
case JVM_SIGNATURE_VOID:
{
_index++;
}
break;
case JVM_SIGNATURE_CLASS:
{
while (sig->char_at(_index++) != JVM_SIGNATURE_ENDCLASS) ;
}
break;
case JVM_SIGNATURE_ARRAY:
{
while (sig->char_at(++_index) == JVM_SIGNATURE_ARRAY) ;
if (sig->char_at(_index) == JVM_SIGNATURE_CLASS) {
while (sig->char_at(_index++) != JVM_SIGNATURE_ENDCLASS) ;
} else { } else {
_index++; _param_size += 1; // this is the convention for Method::compute_size_of_parameters
}
}
break;
default:
ShouldNotReachHere();
break;
}
}
expect(JVM_SIGNATURE_ENDFUNC);
// Parse return type
_parameter_index = -1;
parse_type();
check_signature_end();
_parameter_index = 0;
} }
// Detect overflow. (We counted _param_size correctly.)
void SignatureIterator::iterate() { if (_method == NULL && _param_size > fp_max_size_of_parameters) {
// Parse parameters // We did a one-pass computation of argument size, return type,
_parameter_index = 0; // and fingerprint.
_index = 0; _fingerprint = overflow_fingerprint();
expect(JVM_SIGNATURE_FUNC); return;
while (_signature->char_at(_index) != JVM_SIGNATURE_ENDFUNC) _parameter_index += parse_type();
expect(JVM_SIGNATURE_ENDFUNC);
// Parse return type
_parameter_index = -1;
parse_type();
check_signature_end();
_parameter_index = 0;
} }
assert(_shift_count < BitsPerLong,
"shift count overflow %d (%d vs. %d): %s",
_shift_count, _param_size, fp_max_size_of_parameters,
_signature->as_C_string());
assert((_accumulator >> _shift_count) == fp_parameters_done, "must be zero");
// This is the result, along with _return_type:
_fingerprint = _accumulator;
// Cache the result on the method itself:
if (_method != NULL) {
_method->constMethod()->set_fingerprint(_fingerprint);
}
}
// Implementation of SignatureStream // Implementation of SignatureStream
SignatureStream::SignatureStream(Symbol* signature, bool is_method) :
_signature(signature), _at_return_type(false), _previous_name(NULL), _names(NULL) { static inline int decode_signature_char(int ch) {
_begin = _end = (is_method ? 1 : 0); // skip first '(' in method signatures switch (ch) {
#define EACH_SIG(ch, bt, ignore) \
case ch: return bt;
SIGNATURE_TYPES_DO(EACH_SIG, ignore)
#undef EACH_SIG
}
return 0;
}
SignatureStream::SignatureStream(const Symbol* signature,
bool is_method) {
assert(!is_method || signature->starts_with(JVM_SIGNATURE_FUNC),
"method signature required");
_signature = signature;
_limit = signature->utf8_length();
int oz = (is_method ? 1 : 0);
_state = oz;
assert(_state == (int)(is_method ? _s_method : _s_field), "signature state incorrectly set");
_begin = _end = oz; // skip first '(' in method signatures
_array_prefix = 0; // just for definiteness
_previous_name = NULL;
_names = NULL;
next(); next();
} }
@ -279,33 +204,101 @@ SignatureStream::~SignatureStream() {
for (int i = 0; i < _names->length(); i++) { for (int i = 0; i < _names->length(); i++) {
_names->at(i)->decrement_refcount(); _names->at(i)->decrement_refcount();
} }
} else if (_previous_name != NULL && !_previous_name->is_permanent()) {
_previous_name->decrement_refcount();
} }
} }
bool SignatureStream::is_done() const { inline int SignatureStream::scan_non_primitive(BasicType type) {
return _end > _signature->utf8_length(); const u1* base = _signature->bytes();
} int end = _end;
int limit = _limit;
const u1* tem;
switch (type) {
case T_OBJECT:
tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end);
end = (tem == NULL ? limit : tem+1 - base);
break;
case T_ARRAY:
void SignatureStream::next_non_primitive(int t) { while ((end < limit) && ((char)base[end] == JVM_SIGNATURE_ARRAY)) { end++; }
switch (t) { _array_prefix = end - _end; // number of '[' chars just skipped
case JVM_SIGNATURE_CLASS: { if (Signature::has_envelope(base[end++])) {
_type = T_OBJECT; tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end);
Symbol* sig = _signature; end = (tem == NULL ? limit : tem+1 - base);
while (sig->char_at(_end++) != JVM_SIGNATURE_ENDCLASS);
break; break;
} }
case JVM_SIGNATURE_ARRAY: { break;
_type = T_ARRAY;
Symbol* sig = _signature; default : ShouldNotReachHere();
char c = sig->char_at(_end);
while ('0' <= c && c <= '9') c = sig->char_at(_end++);
while (sig->char_at(_end) == JVM_SIGNATURE_ARRAY) {
_end++;
c = sig->char_at(_end);
while ('0' <= c && c <= '9') c = sig->char_at(_end++);
} }
switch(sig->char_at(_end)) { return end;
}
void SignatureStream::next() {
const Symbol* sig = _signature;
int len = _limit;
if (_end >= len) { set_done(); return; }
_begin = _end;
int ch = sig->char_at(_begin);
int btcode = decode_signature_char(ch);
if (btcode == 0) {
guarantee(ch == JVM_SIGNATURE_ENDFUNC, "bad signature char %c/%d", ch, ch);
assert(_state == _s_method, "must be in method");
_state = _s_method_return;
_begin = ++_end;
if (_end >= len) { set_done(); return; }
ch = sig->char_at(_begin);
btcode = decode_signature_char(ch);
}
BasicType bt = (BasicType) btcode;
assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch);
_type = bt;
if (!is_reference_type(bt)) {
// Skip over a single character for a primitive type (or void).
_end++;
return;
}
_end = scan_non_primitive(bt);
}
int SignatureStream::skip_array_prefix(int max_skip_length) {
if (_type != T_ARRAY) {
return 0;
}
if (_array_prefix > max_skip_length) {
// strip some but not all levels of T_ARRAY
_array_prefix -= max_skip_length;
_begin += max_skip_length;
return max_skip_length;
}
// we are stripping all levels of T_ARRAY,
// so we must decode the next character
int whole_array_prefix = _array_prefix;
int new_begin = _begin + whole_array_prefix;
_begin = new_begin;
int ch = _signature->char_at(new_begin);
int btcode = decode_signature_char(ch);
BasicType bt = (BasicType) btcode;
assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch);
_type = bt;
assert(bt != T_VOID && bt != T_ARRAY, "bad signature type");
// Don't bother to call scan_non_primitive, since it won't
// change the value of _end.
return whole_array_prefix;
}
bool Signature::is_valid_array_signature(const Symbol* sig) {
assert(sig->utf8_length() > 1, "this should already have been checked");
assert(sig->char_at(0) == JVM_SIGNATURE_ARRAY, "this should already have been checked");
// The first character is already checked
int i = 1;
int len = sig->utf8_length();
// First skip all '['s
while(i < len - 1 && sig->char_at(i) == JVM_SIGNATURE_ARRAY) i++;
// Check type
switch(sig->char_at(i)) {
case JVM_SIGNATURE_BYTE: case JVM_SIGNATURE_BYTE:
case JVM_SIGNATURE_CHAR: case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_DOUBLE: case JVM_SIGNATURE_DOUBLE:
@ -313,50 +306,60 @@ void SignatureStream::next_non_primitive(int t) {
case JVM_SIGNATURE_INT: case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_LONG: case JVM_SIGNATURE_LONG:
case JVM_SIGNATURE_SHORT: case JVM_SIGNATURE_SHORT:
case JVM_SIGNATURE_BOOLEAN:_end++; break; case JVM_SIGNATURE_BOOLEAN:
default: { // If it is an array, the type is the last character
while (sig->char_at(_end++) != JVM_SIGNATURE_ENDCLASS); return (i + 1 == len);
break; case JVM_SIGNATURE_CLASS:
} // If it is an object, the last character must be a ';'
} return sig->char_at(len - 1) == JVM_SIGNATURE_ENDCLASS;
break;
}
case JVM_SIGNATURE_ENDFUNC: _end++; next(); _at_return_type = true; break;
default : ShouldNotReachHere();
} }
return false;
} }
BasicType Signature::basic_type(int ch) {
bool SignatureStream::is_object() const { int btcode = decode_signature_char(ch);
return _type == T_OBJECT if (btcode == 0) return T_ILLEGAL;
|| _type == T_ARRAY; return (BasicType) btcode;
} }
bool SignatureStream::is_array() const { static const int jl_len = 10, object_len = 6, jl_object_len = jl_len + object_len;
return _type == T_ARRAY; static const char jl_str[] = "java/lang/";
}
Symbol* SignatureStream::as_symbol() { #ifdef ASSERT
static bool signature_symbols_sane() {
static bool done;
if (done) return true;
done = true;
// test some tense code that looks for common symbol names:
assert(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len &&
vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) &&
vmSymbols::java_lang_Object()->ends_with("Object", object_len) &&
vmSymbols::java_lang_Object()->is_permanent() &&
vmSymbols::java_lang_String()->utf8_length() == jl_object_len &&
vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) &&
vmSymbols::java_lang_String()->ends_with("String", object_len) &&
vmSymbols::java_lang_String()->is_permanent(),
"sanity");
return true;
}
#endif //ASSERT
// returns a symbol; the caller is responsible for decrementing it
Symbol* SignatureStream::find_symbol() {
// Create a symbol from for string _begin _end // Create a symbol from for string _begin _end
int begin = _begin; int begin = raw_symbol_begin();
int end = _end; int end = raw_symbol_end();
if ( _signature->char_at(_begin) == JVM_SIGNATURE_CLASS
&& _signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS) {
begin++;
end--;
}
const char* symbol_chars = (const char*)_signature->base() + begin; const char* symbol_chars = (const char*)_signature->base() + begin;
int len = end - begin; int len = end - begin;
// Quick check for common symbols in signatures // Quick check for common symbols in signatures
assert((vmSymbols::java_lang_String()->utf8_length() == 16 && vmSymbols::java_lang_Object()->utf8_length() == 16), "sanity"); assert(signature_symbols_sane(), "incorrect signature sanity check");
if (len == 16 && if (len == jl_object_len &&
strncmp(symbol_chars, "java/lang/", 10) == 0) { memcmp(symbol_chars, jl_str, jl_len) == 0) {
if (strncmp("String", symbol_chars + 10, 6) == 0) { if (memcmp("String", symbol_chars + jl_len, object_len) == 0) {
return vmSymbols::java_lang_String(); return vmSymbols::java_lang_String();
} else if (strncmp("Object", symbol_chars + 10, 6) == 0) { } else if (memcmp("Object", symbol_chars + jl_len, object_len) == 0) {
return vmSymbols::java_lang_Object(); return vmSymbols::java_lang_Object();
} }
} }
@ -369,7 +372,17 @@ Symbol* SignatureStream::as_symbol() {
// Save names for cleaning up reference count at the end of // Save names for cleaning up reference count at the end of
// SignatureStream scope. // SignatureStream scope.
name = SymbolTable::new_symbol(symbol_chars, len); name = SymbolTable::new_symbol(symbol_chars, len);
if (!name->is_permanent()) {
// Only allocate the GrowableArray for the _names buffer if more than
// one name is being processed in the signature.
if (_previous_name != NULL &&
!_previous_name->is_permanent() &&
!name->is_permanent() &&
_names == NULL) {
_names = new GrowableArray<Symbol*>(10);
_names->push(_previous_name);
}
if (!name->is_permanent() && _previous_name != NULL) {
if (_names == NULL) { if (_names == NULL) {
_names = new GrowableArray<Symbol*>(10); _names = new GrowableArray<Symbol*>(10);
} }
@ -381,57 +394,67 @@ Symbol* SignatureStream::as_symbol() {
Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain, Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
FailureMode failure_mode, TRAPS) { FailureMode failure_mode, TRAPS) {
if (!is_object()) return NULL; if (!is_reference()) return NULL;
Symbol* name = as_symbol(); Symbol* name = as_symbol();
Klass* k = NULL;
if (failure_mode == ReturnNull) { if (failure_mode == ReturnNull) {
return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD); // Note: SD::resolve_or_null returns NULL for most failure modes,
// but not all. Circularity errors, invalid PDs, etc., throw.
k = SystemDictionary::resolve_or_null(name, class_loader, protection_domain, CHECK_NULL);
} else if (failure_mode == CachedOrNull) {
NoSafepointVerifier nsv; // no loading, now, we mean it!
assert(!HAS_PENDING_EXCEPTION, "");
k = SystemDictionary::find(name, class_loader, protection_domain, CHECK_NULL);
// SD::find does not trigger loading, so there should be no throws
// Still, bad things can happen, so we CHECK_NULL and ask callers
// to do likewise.
return k;
} else { } else {
// The only remaining failure mode is NCDFError.
// The test here allows for an additional mode CNFException
// if callers need to request the reflective error instead.
bool throw_error = (failure_mode == NCDFError); bool throw_error = (failure_mode == NCDFError);
return SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, THREAD); k = SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, CHECK_NULL);
} }
return k;
} }
oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain, oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
FailureMode failure_mode, TRAPS) { FailureMode failure_mode, TRAPS) {
if (!is_object()) if (!is_reference())
return Universe::java_mirror(type()); return Universe::java_mirror(type());
Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
if (klass == NULL) return NULL; if (klass == NULL) return NULL;
return klass->java_mirror(); return klass->java_mirror();
} }
Symbol* SignatureStream::as_symbol_or_null() { void SignatureStream::skip_to_return_type() {
// Create a symbol from for string _begin _end while (!at_return_type()) {
ResourceMark rm; next();
int begin = _begin;
int end = _end;
if ( _signature->char_at(_begin) == JVM_SIGNATURE_CLASS
&& _signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS) {
begin++;
end--;
} }
char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
for (int index = begin; index < end; index++) {
buffer[index - begin] = _signature->char_at(index);
}
Symbol* result = SymbolTable::probe(buffer, end - begin);
return result;
}
int SignatureStream::reference_parameter_count() {
int args_count = 0;
for ( ; !at_return_type(); next()) {
if (is_object()) {
args_count++;
}
}
return args_count;
} }
#ifdef ASSERT #ifdef ASSERT
extern bool signature_constants_sane(); // called from basic_types_init()
bool signature_constants_sane() {
// for the lookup table, test every 8-bit code point, and then some:
for (int i = -256; i <= 256; i++) {
int btcode = 0;
switch (i) {
#define EACH_SIG(ch, bt, ignore) \
case ch: { btcode = bt; break; }
SIGNATURE_TYPES_DO(EACH_SIG, ignore)
#undef EACH_SIG
}
int btc = decode_signature_char(i);
assert(btc == btcode, "misconfigured table: %d => %d not %d", i, btc, btcode);
}
return true;
}
bool SignatureVerifier::is_valid_method_signature(Symbol* sig) { bool SignatureVerifier::is_valid_method_signature(Symbol* sig) {
const char* method_sig = (const char*)sig->bytes(); const char* method_sig = (const char*)sig->bytes();
ssize_t len = sig->utf8_length(); ssize_t len = sig->utf8_length();
@ -476,8 +499,8 @@ ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
switch (type[index]) { switch (type[index]) {
case JVM_SIGNATURE_BYTE: case JVM_SIGNATURE_BYTE:
case JVM_SIGNATURE_CHAR: case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_DOUBLE:
case JVM_SIGNATURE_FLOAT: case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_DOUBLE:
case JVM_SIGNATURE_INT: case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_LONG: case JVM_SIGNATURE_LONG:
case JVM_SIGNATURE_SHORT: case JVM_SIGNATURE_SHORT:
@ -500,4 +523,5 @@ ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
} }
return -1; return -1;
} }
#endif // ASSERT #endif // ASSERT

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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,102 +25,232 @@
#ifndef SHARE_RUNTIME_SIGNATURE_HPP #ifndef SHARE_RUNTIME_SIGNATURE_HPP
#define SHARE_RUNTIME_SIGNATURE_HPP #define SHARE_RUNTIME_SIGNATURE_HPP
#include "classfile/symbolTable.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "oops/method.hpp" #include "oops/method.hpp"
// SignatureIterators iterate over a Java signature (or parts of it).
// (Syntax according to: "The Java Virtual Machine Specification" by // Static routines and parsing loops for processing field and method
// Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.) // descriptors. In the HotSpot sources we call them "signatures".
// //
// Example: Iterating over ([Lfoo;D)I using // A SignatureStream iterates over a Java descriptor (or parts of it).
// 0123456789 // The syntax is documented in the Java Virtual Machine Specification,
// section 4.3.
// //
// iterate_parameters() calls: do_array(2, 7); do_double(); // The syntax may be summarized as follows:
// iterate_returntype() calls: do_int();
// iterate() calls: do_array(2, 7); do_double(); do_int();
// //
// is_return_type() is: false ; false ; true // MethodType: '(' {FieldType}* ')' (FieldType | 'V')
// FieldType: PrimitiveType | ObjectType | ArrayType
// PrimitiveType: 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z'
// ObjectType: 'L' ClassName ';' | ArrayType
// ArrayType: '[' FieldType
// ClassName: {UnqualifiedName '/'}* UnqualifiedName
// UnqualifiedName: NameChar {NameChar}*
// NameChar: ANY_CHAR_EXCEPT('/' | '.' | ';' | '[')
// //
// NOTE: The new optimizer has an alternate, for-loop based signature // All of the concrete characters in the above grammar are given
// iterator implemented in opto/type.cpp, TypeTuple::make(). // standard manifest constant names of the form JVM_SIGNATURE_x.
// Executable code uses these constant names in preference to raw
// character constants. Comments and assertion code sometimes use
// the raw character constants for brevity.
//
// The primitive field types (like 'I') correspond 1-1 with type codes
// (like T_INT) which form part of the specification of the 'newarray'
// instruction (JVMS 6.5, section on newarray). These type codes are
// widely used in the HotSpot code. They are joined by ad hoc codes
// like T_OBJECT and T_ARRAY (defined in HotSpot but not in the JVMS)
// so that each "basic type" of field descriptor (or void return type)
// has a corresponding T_x code. Thus, while T_x codes play a very
// minor role in the JVMS, they play a major role in the HotSpot
// sources. There are fewer than 16 such "basic types", so they fit
// nicely into bitfields.
//
// The syntax of ClassName overlaps slightly with the descriptor
// syntaxes. The strings "I" and "(I)V" are both class names
// *and* descriptors. If a class name contains any character other
// than "BCDFIJSZ()V" it cannot be confused with a descriptor.
// Class names inside of descriptors are always contained in an
// "envelope" syntax which starts with 'L' and ends with ';'.
//
// As a confounding factor, array types report their type name strings
// in descriptor format. These name strings are easy to recognize,
// since they begin with '['. For this reason some API points on
// HotSpot look for array descriptors as well as proper class names.
//
// For historical reasons some API points that accept class names and
// array names also look for class names wrapped inside an envelope
// (like "LFoo;") and unwrap them on the fly (to a name like "Foo").
class Signature : AllStatic {
private:
static bool is_valid_array_signature(const Symbol* sig);
public:
// Returns the basic type of a field signature (or T_VOID for "V").
// Assumes the signature is a valid field descriptor.
// Do not apply this function to class names or method signatures.
static BasicType basic_type(const Symbol* signature) {
return basic_type(signature->char_at(0));
}
// Returns T_ILLEGAL for an illegal signature char.
static BasicType basic_type(int ch);
// Assuming it is either a class name or signature,
// determine if it in fact cannot be a class name.
// This means it either starts with '[' or ends with ';'
static bool not_class_name(const Symbol* signature) {
return (signature->starts_with(JVM_SIGNATURE_ARRAY) ||
signature->ends_with(JVM_SIGNATURE_ENDCLASS));
}
// Assuming it is either a class name or signature,
// determine if it in fact is an array descriptor.
static bool is_array(const Symbol* signature) {
return (signature->utf8_length() > 1 &&
signature->char_at(0) == JVM_SIGNATURE_ARRAY &&
is_valid_array_signature(signature));
}
// Assuming it is either a class name or signature,
// determine if it contains a class name plus ';'.
static bool has_envelope(const Symbol* signature) {
return ((signature->utf8_length() > 0) &&
signature->ends_with(JVM_SIGNATURE_ENDCLASS) &&
has_envelope(signature->char_at(0)));
}
// Determine if this signature char introduces an
// envelope, which is a class name plus ';'.
static bool has_envelope(char signature_char) {
return (signature_char == JVM_SIGNATURE_CLASS);
}
// Assuming has_envelope is true, return the symbol
// inside the envelope, by stripping 'L' and ';'.
// Caller is responsible for decrementing the newly created
// Symbol's refcount, use TempNewSymbol.
static Symbol* strip_envelope(const Symbol* signature) {
assert(has_envelope(signature), "precondition");
return SymbolTable::new_symbol((char*) signature->bytes() + 1,
signature->utf8_length() - 2);
}
// Assuming it's either a field or method descriptor, determine
// whether it is in fact a method descriptor:
static bool is_method(const Symbol* signature) {
return signature->starts_with(JVM_SIGNATURE_FUNC);
}
// Assuming it's a method signature, determine if it must
// return void.
static bool is_void_method(const Symbol* signature) {
assert(is_method(signature), "signature is not for a method");
return signature->ends_with(JVM_SIGNATURE_VOID);
}
};
// A SignatureIterator uses a SignatureStream to produce BasicType
// results, discarding class names. This means it can be accelerated
// using a fingerprint mechanism, in many cases, without loss of type
// information. The FingerPrinter class computes and caches this
// reduced information for faster iteration.
class SignatureIterator: public ResourceObj { class SignatureIterator: public ResourceObj {
public:
typedef uint64_t fingerprint_t;
protected: protected:
Symbol* _signature; // the signature to iterate over Symbol* _signature; // the signature to iterate over
int _index; // the current character index (only valid during iteration)
int _parameter_index; // the current parameter index (0 outside iteration phase)
BasicType _return_type; BasicType _return_type;
fingerprint_t _fingerprint;
void expect(char c);
int parse_type(); // returns the parameter size in words (0 for void)
void check_signature_end();
public: public:
// Definitions used in generating and iterating the // Definitions used in generating and iterating the
// bit field form of the signature generated by the // bit field form of the signature generated by the
// Fingerprinter. // Fingerprinter.
enum { enum {
static_feature_size = 1, fp_static_feature_size = 1,
is_static_bit = 1, fp_is_static_bit = 1,
result_feature_size = 4, fp_result_feature_size = 4,
result_feature_mask = 0xF, fp_result_feature_mask = right_n_bits(fp_result_feature_size),
parameter_feature_size = 4, fp_parameter_feature_size = 4,
parameter_feature_mask = 0xF, fp_parameter_feature_mask = right_n_bits(fp_parameter_feature_size),
bool_parm = 1, fp_parameters_done = 0, // marker for end of parameters (must be zero)
byte_parm = 2,
char_parm = 3,
short_parm = 4,
int_parm = 5,
long_parm = 6,
float_parm = 7,
double_parm = 8,
obj_parm = 9,
done_parm = 10, // marker for end of parameters
// max parameters is wordsize minus // Parameters take up full wordsize, minus the result and static bit fields.
// The sign bit, termination field, the result and static bit fields // Since fp_parameters_done is zero, termination field arises from shifting
max_size_of_parameters = (BitsPerLong-1 - // in zero bits, and therefore occupies no extra space.
result_feature_size - parameter_feature_size - // The sentinel value is all-zero-bits, which is impossible for a true
static_feature_size) / parameter_feature_size // fingerprint, since at least the result field will be non-zero.
fp_max_size_of_parameters = ((BitsPerLong
- (fp_result_feature_size + fp_static_feature_size))
/ fp_parameter_feature_size)
}; };
static bool fp_is_valid_type(BasicType type, bool for_return_type = false);
// Sentinel values are zero and not-zero (-1).
// No need to protect the sign bit, since every valid return type is non-zero
// (even T_VOID), and there are no valid parameter fields which are 0xF (T_VOID).
static fingerprint_t zero_fingerprint() { return (fingerprint_t)0; }
static fingerprint_t overflow_fingerprint() { return ~(fingerprint_t)0; }
static bool fp_is_valid(fingerprint_t fingerprint) {
return (fingerprint != zero_fingerprint()) && (fingerprint != overflow_fingerprint());
}
// Constructors // Constructors
SignatureIterator(Symbol* signature); SignatureIterator(Symbol* signature, fingerprint_t fingerprint = zero_fingerprint()) {
_signature = signature;
_return_type = T_ILLEGAL; // sentinel value for uninitialized
_fingerprint = zero_fingerprint();
if (fingerprint != _fingerprint) {
set_fingerprint(fingerprint);
}
}
// If the fingerprint is present, we can use an accelerated loop.
void set_fingerprint(fingerprint_t fingerprint);
// Returns the set fingerprint, or zero_fingerprint()
// if none has been set already.
fingerprint_t fingerprint() const { return _fingerprint; }
// Iteration // Iteration
void iterate_parameters(); // iterates over parameters only // Hey look: There are no virtual methods in this class.
void iterate_parameters( uint64_t fingerprint ); // So how is it customized? By calling do_parameters_on
void iterate_returntype(); // iterates over returntype only // an object which answers to "do_type(BasicType)".
void iterate(); // iterates over whole signature // By convention, this object is in the subclass
// Returns the word index of the current parameter; // itself, so the call is "do_parameters_on(this)".
int parameter_index() const { return _parameter_index; } // The effect of this is to inline the parsing loop
bool is_return_type() const { return parameter_index() < 0; } // everywhere "do_parameters_on" is called.
BasicType get_ret_type() const { return _return_type; } // If there is a valid fingerprint in the object,
// an improved loop is called which just unpacks the
// bitfields from the fingerprint. Otherwise, the
// symbol is parsed.
template<typename T> inline void do_parameters_on(T* callback); // iterates over parameters only
void skip_parameters(); // skips over parameters to find return type
BasicType return_type(); // computes the value on the fly if necessary
// Basic types static bool fp_is_static(fingerprint_t fingerprint) {
virtual void do_bool () = 0; assert(fp_is_valid(fingerprint), "invalid fingerprint");
virtual void do_char () = 0; return fingerprint & fp_is_static_bit;
virtual void do_float () = 0;
virtual void do_double() = 0;
virtual void do_byte () = 0;
virtual void do_short () = 0;
virtual void do_int () = 0;
virtual void do_long () = 0;
virtual void do_void () = 0;
// Object types (begin indexes the first character of the entry, end indexes the first character after the entry)
virtual void do_object(int begin, int end) = 0;
virtual void do_array (int begin, int end) = 0;
static bool is_static(uint64_t fingerprint) {
assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
return fingerprint & is_static_bit;
} }
static BasicType return_type(uint64_t fingerprint) { static BasicType fp_return_type(fingerprint_t fingerprint) {
assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint"); assert(fp_is_valid(fingerprint), "invalid fingerprint");
return (BasicType) ((fingerprint >> static_feature_size) & result_feature_mask); return (BasicType) ((fingerprint >> fp_static_feature_size) & fp_result_feature_mask);
}
static fingerprint_t fp_start_parameters(fingerprint_t fingerprint) {
assert(fp_is_valid(fingerprint), "invalid fingerprint");
return fingerprint >> (fp_static_feature_size + fp_result_feature_size);
}
static BasicType fp_next_parameter(fingerprint_t& mask) {
int result = (mask & fp_parameter_feature_mask);
mask >>= fp_parameter_feature_size;
return (BasicType) result;
} }
}; };
@ -131,87 +261,70 @@ class SignatureTypeNames : public SignatureIterator {
protected: protected:
virtual void type_name(const char* name) = 0; virtual void type_name(const char* name) = 0;
void do_bool() { type_name("jboolean"); } friend class SignatureIterator; // so do_parameters_on can call do_type
void do_char() { type_name("jchar" ); } void do_type(BasicType type) {
void do_float() { type_name("jfloat" ); } switch (type) {
void do_double() { type_name("jdouble" ); } case T_BOOLEAN: type_name("jboolean"); break;
void do_byte() { type_name("jbyte" ); } case T_CHAR: type_name("jchar" ); break;
void do_short() { type_name("jshort" ); } case T_FLOAT: type_name("jfloat" ); break;
void do_int() { type_name("jint" ); } case T_DOUBLE: type_name("jdouble" ); break;
void do_long() { type_name("jlong" ); } case T_BYTE: type_name("jbyte" ); break;
void do_void() { type_name("void" ); } case T_SHORT: type_name("jshort" ); break;
void do_object(int begin, int end) { type_name("jobject" ); } case T_INT: type_name("jint" ); break;
void do_array (int begin, int end) { type_name("jobject" ); } case T_LONG: type_name("jlong" ); break;
case T_VOID: type_name("void" ); break;
case T_ARRAY:
case T_OBJECT: type_name("jobject" ); break;
default: ShouldNotReachHere();
}
}
public: public:
SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {} SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {}
}; };
class SignatureInfo: public SignatureIterator {
protected:
bool _has_iterated; // need this because iterate cannot be called in constructor (set is virtual!)
bool _has_iterated_return;
int _size;
void lazy_iterate_parameters() { if (!_has_iterated) { iterate_parameters(); _has_iterated = true; } }
void lazy_iterate_return() { if (!_has_iterated_return) { iterate_returntype(); _has_iterated_return = true; } }
virtual void set(int size, BasicType type) = 0;
void do_bool () { set(T_BOOLEAN_size, T_BOOLEAN); }
void do_char () { set(T_CHAR_size , T_CHAR ); }
void do_float () { set(T_FLOAT_size , T_FLOAT ); }
void do_double() { set(T_DOUBLE_size , T_DOUBLE ); }
void do_byte () { set(T_BYTE_size , T_BYTE ); }
void do_short () { set(T_SHORT_size , T_SHORT ); }
void do_int () { set(T_INT_size , T_INT ); }
void do_long () { set(T_LONG_size , T_LONG ); }
void do_void () { set(T_VOID_size , T_VOID ); }
void do_object(int begin, int end) { set(T_OBJECT_size , T_OBJECT ); }
void do_array (int begin, int end) { set(T_ARRAY_size , T_ARRAY ); }
public:
SignatureInfo(Symbol* signature) : SignatureIterator(signature) {
_has_iterated = _has_iterated_return = false;
_size = 0;
_return_type = T_ILLEGAL;
}
};
// Specialized SignatureIterator: Used to compute the argument size. // Specialized SignatureIterator: Used to compute the argument size.
class ArgumentSizeComputer: public SignatureInfo { class ArgumentSizeComputer: public SignatureIterator {
private: private:
void set(int size, BasicType type) { _size += size; } int _size;
friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) { _size += parameter_type_word_count(type); }
public: public:
ArgumentSizeComputer(Symbol* signature) : SignatureInfo(signature) {} ArgumentSizeComputer(Symbol* signature);
int size() { return _size; }
int size() { lazy_iterate_parameters(); return _size; }
}; };
class ArgumentCount: public SignatureInfo { class ArgumentCount: public SignatureIterator {
private: private:
void set(int size, BasicType type) { _size ++; } int _size;
friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) { _size++; }
public: public:
ArgumentCount(Symbol* signature) : SignatureInfo(signature) {} ArgumentCount(Symbol* signature);
int size() { return _size; }
};
int size() { lazy_iterate_parameters(); return _size; }
class ReferenceArgumentCount: public SignatureIterator {
private:
int _refs;
friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) { if (is_reference_type(type)) _refs++; }
public:
ReferenceArgumentCount(Symbol* signature);
int count() { return _refs; }
}; };
// Specialized SignatureIterator: Used to compute the result type. // Specialized SignatureIterator: Used to compute the result type.
class ResultTypeFinder: public SignatureInfo { class ResultTypeFinder: public SignatureIterator {
private:
void set(int size, BasicType type) { _return_type = type; }
public: public:
BasicType type() { lazy_iterate_return(); return _return_type; } BasicType type() { return return_type(); }
ResultTypeFinder(Symbol* signature) : SignatureIterator(signature) { }
ResultTypeFinder(Symbol* signature) : SignatureInfo(signature) {}
}; };
@ -219,52 +332,41 @@ class ResultTypeFinder: public SignatureInfo {
// is a bitvector characterizing the methods signature (incl. the receiver). // is a bitvector characterizing the methods signature (incl. the receiver).
class Fingerprinter: public SignatureIterator { class Fingerprinter: public SignatureIterator {
private: private:
uint64_t _fingerprint; fingerprint_t _accumulator;
int _param_size;
int _shift_count; int _shift_count;
methodHandle mh; const Method* _method;
void initialize_accumulator() {
_accumulator = 0;
_shift_count = fp_result_feature_size + fp_static_feature_size;
_param_size = 0;
}
// Out-of-line method does it all in constructor:
void compute_fingerprint_and_return_type(bool static_flag = false);
friend class SignatureIterator; // so do_parameters_on can call do_type
void do_type(BasicType type) {
assert(fp_is_valid_type(type), "bad parameter type");
_accumulator |= ((fingerprint_t)type << _shift_count);
_shift_count += fp_parameter_feature_size;
_param_size += (is_double_word_type(type) ? 2 : 1);
}
public: public:
int size_of_parameters() const { return _param_size; }
// fingerprint() and return_type() are in super class
void do_bool() { _fingerprint |= (((uint64_t)bool_parm) << _shift_count); _shift_count += parameter_feature_size; } Fingerprinter(const methodHandle& method)
void do_char() { _fingerprint |= (((uint64_t)char_parm) << _shift_count); _shift_count += parameter_feature_size; } : SignatureIterator(method->signature()),
void do_byte() { _fingerprint |= (((uint64_t)byte_parm) << _shift_count); _shift_count += parameter_feature_size; } _method(method()) {
void do_short() { _fingerprint |= (((uint64_t)short_parm) << _shift_count); _shift_count += parameter_feature_size; } compute_fingerprint_and_return_type();
void do_int() { _fingerprint |= (((uint64_t)int_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_long() { _fingerprint |= (((uint64_t)long_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_float() { _fingerprint |= (((uint64_t)float_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_double() { _fingerprint |= (((uint64_t)double_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_object(int begin, int end) { _fingerprint |= (((uint64_t)obj_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_array (int begin, int end) { _fingerprint |= (((uint64_t)obj_parm) << _shift_count); _shift_count += parameter_feature_size; }
void do_void() { ShouldNotReachHere(); }
Fingerprinter(const methodHandle& method) : SignatureIterator(method->signature()) {
mh = method;
_fingerprint = 0;
} }
Fingerprinter(Symbol* signature, bool is_static)
uint64_t fingerprint() { : SignatureIterator(signature),
// See if we fingerprinted this method already _method(NULL) {
if (mh->constMethod()->fingerprint() != CONST64(0)) { compute_fingerprint_and_return_type(is_static);
return mh->constMethod()->fingerprint();
}
if (mh->size_of_parameters() > max_size_of_parameters ) {
_fingerprint = (uint64_t)CONST64(-1);
mh->constMethod()->set_fingerprint(_fingerprint);
return _fingerprint;
}
assert( (int)mh->result_type() <= (int)result_feature_mask, "bad result type");
_fingerprint = mh->result_type();
_fingerprint <<= static_feature_size;
if (mh->is_static()) _fingerprint |= 1;
_shift_count = result_feature_size + static_feature_size;
iterate_parameters();
_fingerprint |= ((uint64_t)done_parm) << _shift_count;// mark end of sig
mh->constMethod()->set_fingerprint(_fingerprint);
return _fingerprint;
} }
}; };
@ -281,35 +383,46 @@ class NativeSignatureIterator: public SignatureIterator {
int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static) int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static)
int _jni_offset; // the current parameter offset, starting with 0 int _jni_offset; // the current parameter offset, starting with 0
void do_bool () { pass_int(); _jni_offset++; _offset++; } friend class SignatureIterator; // so do_parameters_on can call do_type
void do_char () { pass_int(); _jni_offset++; _offset++; } void do_type(BasicType type) {
void do_float () { pass_float(); _jni_offset++; _offset++; } switch (type) {
#ifdef _LP64 case T_BYTE:
void do_double() { pass_double(); _jni_offset++; _offset += 2; } case T_SHORT:
#else case T_INT:
void do_double() { pass_double(); _jni_offset += 2; _offset += 2; } case T_BOOLEAN:
#endif case T_CHAR:
void do_byte () { pass_int(); _jni_offset++; _offset++; } pass_int(); _jni_offset++; _offset++;
void do_short () { pass_int(); _jni_offset++; _offset++; } break;
void do_int () { pass_int(); _jni_offset++; _offset++; } case T_FLOAT:
#ifdef _LP64 pass_float(); _jni_offset++; _offset++;
void do_long () { pass_long(); _jni_offset++; _offset += 2; } break;
#else case T_DOUBLE: {
void do_long () { pass_long(); _jni_offset += 2; _offset += 2; } int jni_offset = LP64_ONLY(1) NOT_LP64(2);
#endif pass_double(); _jni_offset += jni_offset; _offset += 2;
void do_void () { ShouldNotReachHere(); } break;
void do_object(int begin, int end) { pass_object(); _jni_offset++; _offset++; } }
void do_array (int begin, int end) { pass_object(); _jni_offset++; _offset++; } case T_LONG: {
int jni_offset = LP64_ONLY(1) NOT_LP64(2);
pass_long(); _jni_offset += jni_offset; _offset += 2;
break;
}
case T_ARRAY:
case T_OBJECT:
pass_object(); _jni_offset++; _offset++;
break;
default:
ShouldNotReachHere();
}
}
public: public:
methodHandle method() const { return _method; } methodHandle method() const { return _method; }
int offset() const { return _offset; } int offset() const { return _offset; }
int jni_offset() const { return _jni_offset + _prepended; } int jni_offset() const { return _jni_offset + _prepended; }
// int java_offset() const { return method()->size_of_parameters() - _offset - 1; }
bool is_static() const { return method()->is_static(); } bool is_static() const { return method()->is_static(); }
virtual void pass_int() = 0; virtual void pass_int() = 0;
virtual void pass_long() = 0; virtual void pass_long() = 0;
virtual void pass_object() = 0; virtual void pass_object() = 0; // objects, arrays, inlines
virtual void pass_float() = 0; virtual void pass_float() = 0;
#ifdef _LP64 #ifdef _LP64
virtual void pass_double() = 0; virtual void pass_double() = 0;
@ -327,7 +440,9 @@ class NativeSignatureIterator: public SignatureIterator {
_prepended = !is_static() ? JNIEnv_words : JNIEnv_words + mirror_words; _prepended = !is_static() ? JNIEnv_words : JNIEnv_words + mirror_words;
} }
// iterate() calles the 2 virtual methods according to the following invocation syntax: void iterate() { iterate(Fingerprinter(method()).fingerprint()); }
// iterate() calls the 3 virtual methods according to the following invocation syntax:
// //
// {pass_int | pass_long | pass_object} // {pass_int | pass_long | pass_object}
// //
@ -335,85 +450,130 @@ class NativeSignatureIterator: public SignatureIterator {
// The offset() values refer to the Java stack offsets but are 0 based and increasing. // The offset() values refer to the Java stack offsets but are 0 based and increasing.
// The java_offset() values count down to 0, and refer to the Java TOS. // The java_offset() values count down to 0, and refer to the Java TOS.
// The jni_offset() values increase from 1 or 2, and refer to C arguments. // The jni_offset() values increase from 1 or 2, and refer to C arguments.
// The method's return type is ignored.
void iterate() { iterate(Fingerprinter(method()).fingerprint()); void iterate(fingerprint_t fingerprint) {
} set_fingerprint(fingerprint);
// Optimized path if we have the bitvector form of signature
void iterate( uint64_t fingerprint ) {
if (!is_static()) { if (!is_static()) {
// handle receiver (not handled by iterate because not in signature) // handle receiver (not handled by iterate because not in signature)
pass_object(); _jni_offset++; _offset++; pass_object(); _jni_offset++; _offset++;
} }
do_parameters_on(this);
SignatureIterator::iterate_parameters( fingerprint );
} }
}; };
// Handy stream for iterating over signature // This is the core parsing logic for iterating over signatures.
// All of the previous classes use this for doing their work.
class SignatureStream : public StackObj { class SignatureStream : public StackObj {
private: private:
Symbol* _signature; const Symbol* _signature;
int _begin; int _begin;
int _end; int _end;
int _limit;
int _array_prefix; // count of '[' before the array element descr
BasicType _type; BasicType _type;
bool _at_return_type; int _state;
Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups
GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced
inline int scan_non_primitive(BasicType type);
Symbol* find_symbol();
enum { _s_field = 0, _s_method = 1, _s_method_return = 3 };
void set_done() {
_state |= -2; // preserve s_method bit
assert(is_done(), "Unable to set state to done");
}
public: public:
bool at_return_type() const { return _at_return_type; } bool is_method_signature() const { return (_state & (int)_s_method) != 0; }
bool is_done() const; bool at_return_type() const { return _state == (int)_s_method_return; }
void next_non_primitive(int t); bool is_done() const { return _state < 0; }
void next() { void next();
Symbol* sig = _signature;
int len = sig->utf8_length();
if (_end >= len) {
_end = len + 1;
return;
}
_begin = _end; SignatureStream(const Symbol* signature, bool is_method = true);
int t = sig->char_at(_begin);
switch (t) {
case JVM_SIGNATURE_BYTE: _type = T_BYTE; break;
case JVM_SIGNATURE_CHAR: _type = T_CHAR; break;
case JVM_SIGNATURE_DOUBLE: _type = T_DOUBLE; break;
case JVM_SIGNATURE_FLOAT: _type = T_FLOAT; break;
case JVM_SIGNATURE_INT: _type = T_INT; break;
case JVM_SIGNATURE_LONG: _type = T_LONG; break;
case JVM_SIGNATURE_SHORT: _type = T_SHORT; break;
case JVM_SIGNATURE_BOOLEAN: _type = T_BOOLEAN; break;
case JVM_SIGNATURE_VOID: _type = T_VOID; break;
default : next_non_primitive(t);
return;
}
_end++;
}
SignatureStream(Symbol* signature, bool is_method = true);
~SignatureStream(); ~SignatureStream();
bool is_object() const; // True if this argument is an object bool is_reference() const { return is_reference_type(_type); }
bool is_array() const; // True if this argument is an array bool is_array() const { return _type == T_ARRAY; }
bool is_primitive() const { return is_java_primitive(_type); }
BasicType type() const { return _type; } BasicType type() const { return _type; }
Symbol* as_symbol();
enum FailureMode { ReturnNull, NCDFError }; const u1* raw_bytes() const { return _signature->bytes() + _begin; }
int raw_length() const { return _end - _begin; }
int raw_begin() const { return _begin; }
int raw_end() const { return _end; }
int raw_symbol_begin() const { return _begin + (has_envelope() ? 1 : 0); }
int raw_symbol_end() const { return _end - (has_envelope() ? 1 : 0); }
char raw_char_at(int i) const {
assert(i < _limit, "index for raw_char_at is over the limit");
return _signature->char_at(i);
}
// True if there is an embedded class name in this type,
// followed by ';'.
bool has_envelope() const {
if (!Signature::has_envelope(_signature->char_at(_begin)))
return false;
// this should always be true, but let's test it:
assert(_signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS, "signature envelope has no semi-colon at end");
return true;
}
// return the symbol for chars in symbol_begin()..symbol_end()
Symbol* as_symbol() {
return find_symbol();
}
// in case you want only the return type:
void skip_to_return_type();
// number of '[' in array prefix
int array_prefix_length() {
return _type == T_ARRAY ? _array_prefix : 0;
}
// In case you want only the array base type,
// reset the stream after skipping some brackets '['.
// (The argument is clipped to array_prefix_length(),
// and if it ends up as zero this call is a nop.
// The default is value skips all brackets '['.)
int skip_array_prefix(int prefix_length = 9999);
// free-standing lookups (bring your own CL/PD pair)
enum FailureMode { ReturnNull, NCDFError, CachedOrNull };
Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS); oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
const u1* raw_bytes() { return _signature->bytes() + _begin; }
int raw_length() { return _end - _begin; }
// return same as_symbol except allocation of new symbols is avoided.
Symbol* as_symbol_or_null();
// count the number of references in the signature
int reference_parameter_count();
}; };
// Here is how all the SignatureIterator classes invoke the
// SignatureStream engine to do their parsing.
template<typename T> inline
void SignatureIterator::do_parameters_on(T* callback) {
fingerprint_t unaccumulator = _fingerprint;
// Check for too many arguments, or missing fingerprint:
if (!fp_is_valid(unaccumulator)) {
SignatureStream ss(_signature);
for (; !ss.at_return_type(); ss.next()) {
callback->do_type(ss.type());
}
// while we are here, capture the return type
_return_type = ss.type();
} else {
// Optimized version of do_parameters when fingerprint is known
assert(_return_type != T_ILLEGAL, "return type already captured from fp");
unaccumulator = fp_start_parameters(unaccumulator);
for (BasicType type; (type = fp_next_parameter(unaccumulator)) != (BasicType)fp_parameters_done; ) {
assert(fp_is_valid_type(type), "garbled fingerprint");
callback->do_type(type);
}
}
}
#ifdef ASSERT #ifdef ASSERT
class SignatureVerifier : public StackObj { class SignatureVerifier : public StackObj {
public: public:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* 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,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "runtime/globals.hpp" #include "runtime/globals.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "runtime/signature.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
// Basic error support // Basic error support
@ -51,6 +52,20 @@ uint64_t OopEncodingHeapMax = 0;
// Something to help porters sleep at night // Something to help porters sleep at night
#ifdef ASSERT
BasicType char2type(int ch) {
switch (ch) {
#define EACH_SIG(ch, bt, ignore) \
case ch: return bt;
SIGNATURE_TYPES_DO(EACH_SIG, ignore)
#undef EACH_SIG
}
return T_ILLEGAL;
}
extern bool signature_constants_sane();
#endif //ASSERT
void basic_types_init() { void basic_types_init() {
#ifdef ASSERT #ifdef ASSERT
#ifdef _LP64 #ifdef _LP64
@ -84,10 +99,13 @@ void basic_types_init() {
assert(wordSize == BytesPerWord, "should be the same since they're used interchangeably"); assert(wordSize == BytesPerWord, "should be the same since they're used interchangeably");
assert(wordSize == HeapWordSize, "should be the same since they're also used interchangeably"); assert(wordSize == HeapWordSize, "should be the same since they're also used interchangeably");
assert(signature_constants_sane(), "");
int num_type_chars = 0; int num_type_chars = 0;
for (int i = 0; i < 99; i++) { for (int i = 0; i < 99; i++) {
if (type2char((BasicType)i) != 0) { if (type2char((BasicType)i) != 0) {
assert(char2type(type2char((BasicType)i)) == i, "proper inverses"); assert(char2type(type2char((BasicType)i)) == i, "proper inverses");
assert(Signature::basic_type(type2char((BasicType)i)) == i, "proper inverses");
num_type_chars++; num_type_chars++;
} }
} }

View file

@ -625,6 +625,24 @@ enum BasicType {
T_ILLEGAL = 99 T_ILLEGAL = 99
}; };
#define SIGNATURE_TYPES_DO(F, N) \
F(JVM_SIGNATURE_BOOLEAN, T_BOOLEAN, N) \
F(JVM_SIGNATURE_CHAR, T_CHAR, N) \
F(JVM_SIGNATURE_FLOAT, T_FLOAT, N) \
F(JVM_SIGNATURE_DOUBLE, T_DOUBLE, N) \
F(JVM_SIGNATURE_BYTE, T_BYTE, N) \
F(JVM_SIGNATURE_SHORT, T_SHORT, N) \
F(JVM_SIGNATURE_INT, T_INT, N) \
F(JVM_SIGNATURE_LONG, T_LONG, N) \
F(JVM_SIGNATURE_CLASS, T_OBJECT, N) \
F(JVM_SIGNATURE_ARRAY, T_ARRAY, N) \
F(JVM_SIGNATURE_VOID, T_VOID, N) \
/*end*/
inline bool is_java_type(BasicType t) {
return T_BOOLEAN <= t && t <= T_VOID;
}
inline bool is_java_primitive(BasicType t) { inline bool is_java_primitive(BasicType t) {
return T_BOOLEAN <= t && t <= T_LONG; return T_BOOLEAN <= t && t <= T_LONG;
} }
@ -646,24 +664,6 @@ inline bool is_reference_type(BasicType t) {
return (t == T_OBJECT || t == T_ARRAY); return (t == T_OBJECT || t == T_ARRAY);
} }
// Convert a char from a classfile signature to a BasicType
inline BasicType char2type(char c) {
switch( c ) {
case JVM_SIGNATURE_BYTE: return T_BYTE;
case JVM_SIGNATURE_CHAR: return T_CHAR;
case JVM_SIGNATURE_DOUBLE: return T_DOUBLE;
case JVM_SIGNATURE_FLOAT: return T_FLOAT;
case JVM_SIGNATURE_INT: return T_INT;
case JVM_SIGNATURE_LONG: return T_LONG;
case JVM_SIGNATURE_SHORT: return T_SHORT;
case JVM_SIGNATURE_BOOLEAN: return T_BOOLEAN;
case JVM_SIGNATURE_VOID: return T_VOID;
case JVM_SIGNATURE_CLASS: return T_OBJECT;
case JVM_SIGNATURE_ARRAY: return T_ARRAY;
}
return T_ILLEGAL;
}
extern char type2char_tab[T_CONFLICT+1]; // Map a BasicType to a jchar extern char type2char_tab[T_CONFLICT+1]; // Map a BasicType to a jchar
inline char type2char(BasicType t) { return (uint)t < T_CONFLICT+1 ? type2char_tab[t] : 0; } inline char type2char(BasicType t) { return (uint)t < T_CONFLICT+1 ? type2char_tab[t] : 0; }
extern int type2size[T_CONFLICT+1]; // Map BasicType to result stack elements extern int type2size[T_CONFLICT+1]; // Map BasicType to result stack elements
@ -693,6 +693,13 @@ enum BasicTypeSize {
T_VOID_size = 0 T_VOID_size = 0
}; };
// this works on valid parameter types but not T_VOID, T_CONFLICT, etc.
inline int parameter_type_word_count(BasicType t) {
if (is_double_word_type(t)) return 2;
assert(is_java_primitive(t) || is_reference_type(t), "no goofy types here please");
assert(type2size[t] == 1, "must be");
return 1;
}
// maps a BasicType to its instance field storage type: // maps a BasicType to its instance field storage type:
// all sub-word integral types are widened to T_INT // all sub-word integral types are widened to T_INT