mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
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:
parent
2ede36b3a3
commit
d19a396e96
57 changed files with 1394 additions and 1498 deletions
|
@ -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.
|
||||
* 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
|
||||
out_sig_bt[argc++] = T_INT;
|
||||
out_sig_bt[argc++] = T_ADDRESS;
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[i] = ss.type();
|
||||
} else {
|
||||
out_sig_bt[argc++] = in_sig_bt[i];
|
||||
in_elem_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* 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++) {
|
||||
if (in_sig_bt[i] == T_ARRAY) {
|
||||
// Arrays are passed as int, elem* pair
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[o] = ss.type();
|
||||
} else {
|
||||
in_elem_bt[o] = 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* 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++) {
|
||||
if (in_sig_bt[i] == T_ARRAY) {
|
||||
// Arrays are passed as tuples (int, elem*).
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[o] = ss.type();
|
||||
} else {
|
||||
in_elem_bt[o] = 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
out_sig_bt[argc++] = T_INT;
|
||||
out_sig_bt[argc++] = T_ADDRESS;
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[i] = ss.type();
|
||||
} else {
|
||||
out_sig_bt[argc++] = in_sig_bt[i];
|
||||
in_elem_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
out_sig_bt[argc++] = T_INT;
|
||||
out_sig_bt[argc++] = T_ADDRESS;
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[i] = ss.type();
|
||||
} else {
|
||||
out_sig_bt[argc++] = in_sig_bt[i];
|
||||
in_elem_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
out_sig_bt[argc++] = T_INT;
|
||||
out_sig_bt[argc++] = T_ADDRESS;
|
||||
Symbol* atype = ss.as_symbol();
|
||||
const char* at = atype->as_C_string();
|
||||
if (strlen(at) == 2) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
ss.skip_array_prefix(1); // skip one '['
|
||||
assert(ss.is_primitive(), "primitive type expected");
|
||||
in_elem_bt[i] = ss.type();
|
||||
} else {
|
||||
out_sig_bt[argc++] = in_sig_bt[i];
|
||||
in_elem_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -265,8 +265,8 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
|
|||
GlobalValueNumbering* _gvn;
|
||||
BlockList _loop_blocks;
|
||||
bool _too_complicated_loop;
|
||||
bool _has_field_store[T_ARRAY + 1];
|
||||
bool _has_indexed_store[T_ARRAY + 1];
|
||||
bool _has_field_store[T_VOID];
|
||||
bool _has_indexed_store[T_VOID];
|
||||
|
||||
// simplified access to methods of GlobalValueNumbering
|
||||
ValueMap* current_map() { return _gvn->current_map(); }
|
||||
|
@ -276,12 +276,12 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
|
|||
void kill_memory() { _too_complicated_loop = true; }
|
||||
void kill_field(ciField* field, bool 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;
|
||||
}
|
||||
void kill_array(ValueType* 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;
|
||||
}
|
||||
|
||||
|
@ -291,19 +291,19 @@ class ShortLoopOptimizer : public ValueNumberingVisitor {
|
|||
, _loop_blocks(ValueMapMaxLoopSize)
|
||||
, _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_indexed_store[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
|
|
@ -413,12 +413,10 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
|
|||
|
||||
// Now we need to check the SystemDictionary
|
||||
Symbol* sym = name->get_symbol();
|
||||
if (sym->char_at(0) == JVM_SIGNATURE_CLASS &&
|
||||
sym->char_at(sym->utf8_length()-1) == JVM_SIGNATURE_ENDCLASS) {
|
||||
if (Signature::has_envelope(sym)) {
|
||||
// This is a name from a signature. Strip off the trimmings.
|
||||
// Call recursive to keep scope of strippedsym.
|
||||
TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
|
||||
sym->utf8_length()-2);
|
||||
TempNewSymbol strippedsym = Signature::strip_envelope(sym);
|
||||
ciSymbol* strippedname = get_symbol(strippedsym);
|
||||
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
|
||||
// to be loaded if their element klasses are loaded, except when memory
|
||||
// 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)) {
|
||||
// We have an unloaded array.
|
||||
// Build it on the fly if the element class exists.
|
||||
TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
|
||||
sym->utf8_length()-1);
|
||||
|
||||
SignatureStream ss(sym, false);
|
||||
ss.skip_array_prefix(1);
|
||||
// Get element ciKlass recursively.
|
||||
ciKlass* elem_klass =
|
||||
get_klass_by_name_impl(accessing_klass,
|
||||
cpool,
|
||||
get_symbol(elem_sym),
|
||||
get_symbol(ss.as_symbol()),
|
||||
require_local);
|
||||
if (elem_klass != NULL && elem_klass->is_loaded()) {
|
||||
// Now make an array for it
|
||||
|
@ -609,7 +606,7 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
|
|||
}
|
||||
BasicType bt = T_OBJECT;
|
||||
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)) {
|
||||
} else {
|
||||
// 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,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
assert(cpool.not_null(), "need constant pool");
|
||||
assert(accessor != NULL, "need origin of access");
|
||||
if (bc == Bytecodes::_invokedynamic) {
|
||||
ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index);
|
||||
bool is_resolved = !cpce->is_f1_null();
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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);
|
||||
_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
|
||||
// field.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 ciMethodData;
|
||||
friend class ciObjArrayKlass;
|
||||
friend class ciSignature;
|
||||
friend class ciReceiverTypeData;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
EXCEPTION_CONTEXT;
|
||||
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();
|
||||
char* name;
|
||||
|
||||
if (base_name_sym->char_at(0) == JVM_SIGNATURE_ARRAY ||
|
||||
(base_name_sym->char_at(0) == JVM_SIGNATURE_CLASS && // watch package name 'Lxx'
|
||||
base_name_sym->char_at(element_len-1) == JVM_SIGNATURE_ENDCLASS)) {
|
||||
|
||||
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';
|
||||
if (Signature::is_array(base_name_sym) ||
|
||||
Signature::has_envelope(base_name_sym)) {
|
||||
strncpy(&name[pos], (char*)element_name->base(), element_len);
|
||||
name[pos + element_len] = '\0';
|
||||
} 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;
|
||||
strncpy(name+pos, (char*)element_name->base(), element_len);
|
||||
name[new_len-2] = JVM_SIGNATURE_ENDCLASS;
|
||||
name[new_len-1] = '\0';
|
||||
strncpy(&name[pos], (char*)element_name->base(), element_len);
|
||||
name[pos + element_len] = JVM_SIGNATURE_ENDCLASS;
|
||||
name[pos + element_len + 1] = '\0';
|
||||
}
|
||||
return ciSymbol::make(name);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -46,7 +46,6 @@
|
|||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
|
@ -418,6 +417,7 @@ ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder,
|
|||
ciSymbol* name,
|
||||
ciSymbol* signature,
|
||||
ciInstanceKlass* accessor) {
|
||||
assert(accessor != NULL, "need origin of access");
|
||||
ciSignature* that = NULL;
|
||||
for (int i = 0; i < _unloaded_methods->length(); i++) {
|
||||
ciMethod* entry = _unloaded_methods->at(i);
|
||||
|
@ -488,20 +488,14 @@ ciKlass* ciObjectFactory::get_unloaded_klass(ciKlass* accessing_klass,
|
|||
// unloaded InstanceKlass. Deal with both.
|
||||
if (name->char_at(0) == JVM_SIGNATURE_ARRAY) {
|
||||
// Decompose the name.'
|
||||
FieldArrayInfo fd;
|
||||
BasicType element_type = FieldType::get_array_info(name->get_symbol(),
|
||||
fd, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
CURRENT_THREAD_ENV->record_out_of_memory_failure();
|
||||
return ciEnv::_unloaded_ciobjarrayklass;
|
||||
}
|
||||
int dimension = fd.dimension();
|
||||
SignatureStream ss(name->get_symbol(), false);
|
||||
int dimension = ss.skip_array_prefix(); // skip all '['s
|
||||
BasicType element_type = ss.type();
|
||||
assert(element_type != T_ARRAY, "unsuccessful decomposition");
|
||||
ciKlass* element_klass = NULL;
|
||||
if (element_type == T_OBJECT) {
|
||||
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 =
|
||||
env->get_klass_by_name(accessing_klass, ci_name, false)->as_instance_klass();
|
||||
} else {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
ASSERT_IN_VM;
|
||||
EXCEPTION_CONTEXT;
|
||||
assert(accessing_klass != NULL, "need origin of access");
|
||||
_accessing_klass = accessing_klass;
|
||||
_symbol = symbol;
|
||||
|
||||
|
@ -55,11 +56,10 @@ ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpo
|
|||
for (; ; ss.next()) {
|
||||
// Process one element of the signature
|
||||
ciType* type;
|
||||
if (!ss.is_object()) {
|
||||
if (!ss.is_reference()) {
|
||||
type = ciType::make(ss.type());
|
||||
} else {
|
||||
Symbol* name = ss.as_symbol();
|
||||
ciSymbol* klass_name = env->get_symbol(name);
|
||||
ciSymbol* klass_name = env->get_symbol(ss.as_symbol());
|
||||
type = env->get_klass_by_name_impl(_accessing_klass, cpool, klass_name, false);
|
||||
}
|
||||
_types->append(type);
|
||||
|
|
|
@ -665,7 +665,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
"Illegal zero length constant pool entry at %d in class %s",
|
||||
name_index, CHECK);
|
||||
|
||||
if (sig->char_at(0) == JVM_SIGNATURE_FUNC) {
|
||||
if (Signature::is_method(sig)) {
|
||||
// Format check method name and signature
|
||||
verify_legal_method_name(name, 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);
|
||||
if (_need_verify) {
|
||||
// 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.
|
||||
if (signature->utf8_length() == 0 ||
|
||||
signature->char_at(0) == JVM_SIGNATURE_FUNC) {
|
||||
// Need only to be sure signature is the right type.
|
||||
if (Signature::is_method(signature)) {
|
||||
throwIllegalSignature("CONSTANT_Dynamic", name, signature, CHECK);
|
||||
}
|
||||
}
|
||||
|
@ -716,8 +715,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
if (_need_verify) {
|
||||
// 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.
|
||||
if (signature->utf8_length() == 0 ||
|
||||
signature->char_at(0) == JVM_SIGNATURE_FUNC) {
|
||||
if (Signature::is_method(signature)) {
|
||||
throwIllegalSignature("Field", name, signature, CHECK);
|
||||
}
|
||||
}
|
||||
|
@ -725,8 +723,7 @@ void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,
|
|||
if (_need_verify) {
|
||||
// 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.
|
||||
if (signature->utf8_length() == 0 ||
|
||||
signature->char_at(0) != JVM_SIGNATURE_FUNC) {
|
||||
if (!Signature::is_method(signature)) {
|
||||
throwIllegalSignature("Method", name, signature, CHECK);
|
||||
}
|
||||
}
|
||||
|
@ -1723,7 +1720,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||
injected[n].signature_index,
|
||||
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
|
||||
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_name_index(name_index);
|
||||
m->set_signature_index(signature_index);
|
||||
|
||||
ResultTypeFinder rtf(cp->symbol_at(signature_index));
|
||||
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
|
||||
m->compute_from_signature(cp->symbol_at(signature_index));
|
||||
assert(args_size < 0 || args_size == m->size_of_parameters(), "");
|
||||
|
||||
// Fill in code attribute information
|
||||
m->set_max_stack(max_stack);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -34,7 +34,6 @@
|
|||
#include "logging/logTag.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/javaCalls.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");
|
||||
}
|
||||
|
||||
bool non_array = !FieldType::is_array(class_name_symbol);
|
||||
bool non_array = !Signature::is_array(class_name_symbol);
|
||||
|
||||
JavaValue result(T_OBJECT);
|
||||
if (non_array) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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_name_index(cp->utf8(name));
|
||||
m->set_signature_index(cp->utf8(sig));
|
||||
ResultTypeFinder rtf(sig);
|
||||
m->constMethod()->set_result_type(rtf.type());
|
||||
m->compute_from_signature(sig);
|
||||
m->set_size_of_parameters(params);
|
||||
m->set_max_stack(max_stack);
|
||||
m->set_max_locals(params);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,7 +27,6 @@
|
|||
#include "classfile/placeholders.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
|
||||
// Placeholder methods
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -28,7 +28,6 @@
|
|||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/constantPool.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
|
||||
StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
#include "prims/methodHandles.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/java.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
|
||||
|
||||
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);
|
||||
} else {
|
||||
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 protection_domain,
|
||||
TRAPS) {
|
||||
assert(class_name != NULL && !FieldType::is_array(class_name), "must be");
|
||||
if (FieldType::is_obj(class_name)) {
|
||||
assert(class_name != NULL && !Signature::is_array(class_name), "must be");
|
||||
if (Signature::has_envelope(class_name)) {
|
||||
ResourceMark rm(THREAD);
|
||||
// Ignore wrapping L and ;.
|
||||
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 protection_domain,
|
||||
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;
|
||||
FieldArrayInfo fd;
|
||||
// dimension and object_key in FieldArrayInfo are assigned as a side-effect
|
||||
// of this call
|
||||
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_NULL);
|
||||
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(),
|
||||
BasicType t = ss.type();
|
||||
if (ss.has_envelope()) {
|
||||
Symbol* obj_class = ss.as_symbol();
|
||||
k = SystemDictionary::resolve_instance_class_or_null(obj_class,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
CHECK_NULL);
|
||||
if (k != NULL) {
|
||||
k = k->array_klass(fd.dimension(), CHECK_NULL);
|
||||
k = k->array_klass(ndims, CHECK_NULL);
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
@ -342,7 +341,7 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
|
|||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
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 (DumpSharedSpaces) {
|
||||
// Special processing for handling UNREGISTERED shared classes.
|
||||
|
@ -654,8 +653,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
|||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
assert(name != NULL && !FieldType::is_array(name) &&
|
||||
!FieldType::is_obj(name), "invalid class name");
|
||||
assert(name != NULL && !Signature::is_array(name) &&
|
||||
!Signature::has_envelope(name), "invalid class name");
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
|
||||
|
@ -960,19 +959,21 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
|||
Klass* k = 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.
|
||||
// dimension and object_key in FieldArrayInfo are assigned as a
|
||||
// side-effect of this call
|
||||
FieldArrayInfo fd;
|
||||
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL));
|
||||
SignatureStream ss(class_name, false);
|
||||
int ndims = ss.skip_array_prefix(); // skip all '['s
|
||||
BasicType t = ss.type();
|
||||
if (t != T_OBJECT) {
|
||||
k = Universe::typeArrayKlassObj(t);
|
||||
} 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) {
|
||||
k = k->array_klass_or_null(fd.dimension());
|
||||
k = k->array_klass_or_null(ndims);
|
||||
}
|
||||
} else {
|
||||
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
|
||||
// a loader constraint that would require this loader to return the
|
||||
// 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
|
||||
// constraint table. The element Klass*s are.
|
||||
FieldArrayInfo fd;
|
||||
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL));
|
||||
SignatureStream ss(class_name, false);
|
||||
int ndims = ss.skip_array_prefix(); // skip all '['s
|
||||
BasicType t = ss.type();
|
||||
if (t != T_OBJECT) {
|
||||
klass = Universe::typeArrayKlassObj(t);
|
||||
} else {
|
||||
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 (klass != NULL) {
|
||||
klass = klass->array_klass_or_null(fd.dimension());
|
||||
klass = klass->array_klass_or_null(ndims);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
|
||||
Symbol* constraint_name = NULL;
|
||||
// Needs to be in same scope as constraint_name in case a Symbol is created and
|
||||
// assigned to constraint_name.
|
||||
FieldArrayInfo fd;
|
||||
if (!FieldType::is_array(class_name)) {
|
||||
|
||||
if (!Signature::is_array(class_name)) {
|
||||
constraint_name = class_name;
|
||||
} else {
|
||||
// For array classes, their Klass*s are not kept in the
|
||||
// constraint table. The element classes are.
|
||||
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(false));
|
||||
// primitive types always pass
|
||||
if (t != T_OBJECT) {
|
||||
return true;
|
||||
} else {
|
||||
constraint_name = fd.object_key();
|
||||
SignatureStream ss(class_name, false);
|
||||
ss.skip_array_prefix(); // skip all '['s
|
||||
if (!ss.has_envelope()) {
|
||||
return true; // primitive types always pass
|
||||
}
|
||||
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();
|
||||
|
@ -2227,8 +2230,12 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
|
|||
MutexLocker mu_s(THREAD, SystemDictionary_lock);
|
||||
InstanceKlass* klass1 = find_class(d_hash1, constraint_name, dictionary1);
|
||||
InstanceKlass* klass2 = find_class(d_hash2, constraint_name, dictionary2);
|
||||
return constraints()->add_entry(constraint_name, klass1, class_loader1,
|
||||
klass2, class_loader2);
|
||||
bool result = constraints()->add_entry(constraint_name, klass1, class_loader1,
|
||||
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;
|
||||
}
|
||||
|
||||
SignatureStream sig_strm(signature, is_method);
|
||||
while (!sig_strm.is_done()) {
|
||||
if (sig_strm.is_object()) {
|
||||
Symbol* sig = sig_strm.as_symbol();
|
||||
for (SignatureStream ss(signature, is_method); !ss.is_done(); ss.next()) {
|
||||
if (ss.is_reference()) {
|
||||
Symbol* sig = ss.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)) {
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
sig_strm.next();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2419,9 +2427,9 @@ static Method* unpack_method_and_appendix(Handle mname,
|
|||
Method* SystemDictionary::find_method_handle_invoker(Klass* klass,
|
||||
Symbol* name,
|
||||
Symbol* signature,
|
||||
Klass* accessing_klass,
|
||||
Handle *appendix_result,
|
||||
TRAPS) {
|
||||
Klass* accessing_klass,
|
||||
Handle *appendix_result,
|
||||
TRAPS) {
|
||||
assert(THREAD->can_call_java() ,"");
|
||||
Handle method_type =
|
||||
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_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
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
// for the given field type signature, as interpreted relative to the
|
||||
// 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()),
|
||||
"one or the other, or perhaps neither");
|
||||
|
||||
Symbol* type = signature;
|
||||
SignatureStream ss(signature, false);
|
||||
|
||||
// What we have here must be a valid field descriptor,
|
||||
// and all valid field descriptors are supported.
|
||||
// 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.)
|
||||
char ch = type->char_at(0);
|
||||
assert(is_java_primitive(char2type(ch)) || ch == JVM_SIGNATURE_VOID, "");
|
||||
return Handle(THREAD, find_java_mirror_for_type(ch));
|
||||
return Handle(THREAD, java_lang_Class::primitive_mirror(ss.type()));
|
||||
|
||||
} else if (FieldType::is_obj(type) || FieldType::is_array(type)) {
|
||||
} else if (ss.is_reference()) {
|
||||
|
||||
// It's a reference type.
|
||||
if (accessing_klass != NULL) {
|
||||
|
@ -2519,11 +2517,11 @@ Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
|
|||
}
|
||||
Klass* constant_type_klass;
|
||||
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));
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
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.
|
||||
mirror = ss.as_java_mirror(Handle(), Handle(),
|
||||
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.
|
||||
can_be_cached = false;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -497,10 +497,6 @@ public:
|
|||
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
|
||||
// (asks Java to compute it if necessary, except in a compiler thread)
|
||||
static Handle find_method_handle_type(Symbol* signature,
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -120,27 +120,29 @@ bool VerificationType::is_reference_assignable_from(
|
|||
|
||||
VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const {
|
||||
assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array");
|
||||
Symbol* component;
|
||||
switch (name()->char_at(1)) {
|
||||
case JVM_SIGNATURE_BOOLEAN: return VerificationType(Boolean);
|
||||
case JVM_SIGNATURE_BYTE: return VerificationType(Byte);
|
||||
case JVM_SIGNATURE_CHAR: return VerificationType(Char);
|
||||
case JVM_SIGNATURE_SHORT: return VerificationType(Short);
|
||||
case JVM_SIGNATURE_INT: return VerificationType(Integer);
|
||||
case JVM_SIGNATURE_LONG: return VerificationType(Long);
|
||||
case JVM_SIGNATURE_FLOAT: return VerificationType(Float);
|
||||
case JVM_SIGNATURE_DOUBLE: return VerificationType(Double);
|
||||
case JVM_SIGNATURE_ARRAY:
|
||||
component = context->create_temporary_symbol(
|
||||
name(), 1, name()->utf8_length());
|
||||
return VerificationType::reference_type(component);
|
||||
case JVM_SIGNATURE_CLASS:
|
||||
component = context->create_temporary_symbol(
|
||||
name(), 2, name()->utf8_length() - 1);
|
||||
return VerificationType::reference_type(component);
|
||||
default:
|
||||
// Met an invalid type signature, e.g. [X
|
||||
return VerificationType::bogus_type();
|
||||
SignatureStream ss(name(), false);
|
||||
ss.skip_array_prefix(1);
|
||||
switch (ss.type()) {
|
||||
case T_BOOLEAN: return VerificationType(Boolean);
|
||||
case T_BYTE: return VerificationType(Byte);
|
||||
case T_CHAR: return VerificationType(Char);
|
||||
case T_SHORT: return VerificationType(Short);
|
||||
case T_INT: return VerificationType(Integer);
|
||||
case T_LONG: return VerificationType(Long);
|
||||
case T_FLOAT: return VerificationType(Float);
|
||||
case T_DOUBLE: return VerificationType(Double);
|
||||
case T_ARRAY:
|
||||
case T_OBJECT: {
|
||||
guarantee(ss.is_reference(), "unchecked verifier input?");
|
||||
Symbol* component = ss.as_symbol();
|
||||
// Create another symbol to save as signature stream unreferences this symbol.
|
||||
Symbol* component_copy = context->create_temporary_symbol(component);
|
||||
assert(component_copy == component, "symbols don't match");
|
||||
return VerificationType::reference_type(component_copy);
|
||||
}
|
||||
default:
|
||||
// Met an invalid type signature, e.g. [X
|
||||
return VerificationType::bogus_type();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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_BOOLEAN] = bool_signature();
|
||||
_type_signatures[T_VOID] = void_signature();
|
||||
// no single signatures for T_OBJECT or T_ARRAY
|
||||
#ifdef ASSERT
|
||||
for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) {
|
||||
Symbol* s = _type_signatures[i];
|
||||
if (s == NULL) continue;
|
||||
BasicType st = signature_type(s);
|
||||
assert(st == i, "");
|
||||
SignatureStream ss(s, false);
|
||||
assert(ss.type() == i, "matching signature");
|
||||
assert(!ss.is_reference(), "no single-char signature for T_OBJECT, etc.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -209,20 +209,6 @@ void vmSymbols::serialize(SerializeClosure* soc) {
|
|||
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;
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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");
|
||||
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) {
|
||||
assert(id >= FIRST_SID && id < SID_LIMIT, "oob");
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -3151,12 +3151,10 @@ void nmethod::print_nmethod_labels(outputStream* stream, address block_begin, bo
|
|||
m->method_holder()->print_value_on(stream);
|
||||
} else {
|
||||
bool did_name = false;
|
||||
if (!at_this && ss.is_object()) {
|
||||
Symbol* name = ss.as_symbol_or_null();
|
||||
if (name != NULL) {
|
||||
name->print_value_on(stream);
|
||||
did_name = true;
|
||||
}
|
||||
if (!at_this && ss.is_reference()) {
|
||||
Symbol* name = ss.as_symbol();
|
||||
name->print_value_on(stream);
|
||||
did_name = true;
|
||||
}
|
||||
if (!did_name)
|
||||
stream->print("%s", type2name(t));
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) ||
|
||||
(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>";
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -28,7 +28,6 @@
|
|||
#include "oops/constantPool.hpp"
|
||||
#include "oops/cpCache.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
|
|
|
@ -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.
|
||||
* 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
|
||||
// from the field.
|
||||
stack->pop(1 - Bytecodes::depth(code));
|
||||
stack->push(bci, char2type((char) signature->char_at(0)));
|
||||
stack->push(bci, Signature::basic_type(signature));
|
||||
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 type_index = cp->signature_ref_index_at(name_and_type_index);
|
||||
Symbol* signature = cp->symbol_at(type_index);
|
||||
ResultTypeFinder result_type(signature);
|
||||
stack->pop(type2size[char2type((char) signature->char_at(0))] - Bytecodes::depth(code) - 1);
|
||||
BasicType bt = Signature::basic_type(signature);
|
||||
stack->pop(type2size[bt] - Bytecodes::depth(code) - 1);
|
||||
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 type_index = cp->signature_ref_index_at(name_and_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::_invokespecial:
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
int handler_index = -1;
|
||||
// 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
|
||||
MutexLocker mu(SignatureHandlerLibrary_lock);
|
||||
// make sure data structure is initialized
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -257,7 +257,7 @@ class MaskFillerForNative: public NativeSignatureIterator {
|
|||
}
|
||||
|
||||
void generate() {
|
||||
NativeSignatureIterator::iterate();
|
||||
iterate();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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_dynamic_constant() &&
|
||||
// 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);
|
||||
if (is_wide) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 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);
|
||||
if (sym != NULL && Signature::has_envelope(sym)) {
|
||||
// Ignore wrapping L and ;
|
||||
sym = Signature::strip_envelope(sym);
|
||||
}
|
||||
if (sym == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
} else {
|
||||
if (class_name->char_at(0) == JVM_SIGNATURE_CLASS &&
|
||||
class_name->char_at(class_name->utf8_length()-1) == JVM_SIGNATURE_ENDCLASS) {
|
||||
if (Signature::has_envelope(class_name)) {
|
||||
// This is a name from a signature. Strip off the trimmings.
|
||||
// Call recursive to keep scope of strippedsym.
|
||||
TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1,
|
||||
class_name->utf8_length()-2);
|
||||
TempNewSymbol strippedsym = Signature::strip_envelope(class_name);
|
||||
resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, CHECK_0);
|
||||
} else if (FieldType::is_array(class_name)) {
|
||||
FieldArrayInfo fd;
|
||||
// dimension and object_key in FieldArrayInfo are assigned as a side-effect
|
||||
// of this call
|
||||
BasicType t = FieldType::get_array_info(class_name, fd, CHECK_0);
|
||||
if (t == T_OBJECT) {
|
||||
TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
|
||||
class_name->utf8_length()-2-fd.dimension());
|
||||
} else if (Signature::is_array(class_name)) {
|
||||
SignatureStream ss(class_name, false);
|
||||
int ndim = ss.skip_array_prefix();
|
||||
if (ss.type() == T_OBJECT) {
|
||||
Symbol* strippedsym = ss.as_symbol();
|
||||
resolved_klass = SystemDictionary::find(strippedsym,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
CHECK_0);
|
||||
class_loader,
|
||||
protection_domain,
|
||||
CHECK_0);
|
||||
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 {
|
||||
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 {
|
||||
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());
|
||||
|
||||
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);
|
||||
JavaCalls::call(&result, mh, &jca, CHECK_NULL);
|
||||
|
||||
if (jap.get_ret_type() == T_VOID) {
|
||||
if (jap.return_type() == T_VOID) {
|
||||
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());
|
||||
} else {
|
||||
jvalue *value = (jvalue *) result.get_value_addr();
|
||||
// Narrow the value down if required (Important on big endian machines)
|
||||
switch (jap.get_ret_type()) {
|
||||
switch (jap.return_type()) {
|
||||
case T_BOOLEAN:
|
||||
value->z = (jboolean) value->i;
|
||||
break;
|
||||
|
@ -1063,7 +1058,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject
|
|||
default:
|
||||
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);
|
||||
}
|
||||
C2V_END
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
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;
|
||||
_jca = jca;
|
||||
_index = 0;
|
||||
|
@ -140,24 +145,31 @@ class JavaArgumentUnboxer : public SignatureIterator {
|
|||
if (!is_static) {
|
||||
_jca->push_oop(next_arg(T_OBJECT));
|
||||
}
|
||||
iterate();
|
||||
do_parameters_on(this);
|
||||
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))); }
|
||||
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))); }
|
||||
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))); }
|
||||
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))); }
|
||||
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))); }
|
||||
|
||||
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))); }
|
||||
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))); }
|
||||
|
||||
inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); }
|
||||
inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
|
||||
inline void do_array(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); }
|
||||
inline void do_void() { }
|
||||
private:
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
if (is_reference_type(type)) {
|
||||
_jca->push_oop(next_arg(T_OBJECT));
|
||||
return;
|
||||
}
|
||||
Handle arg = next_arg(type);
|
||||
int box_offset = java_lang_boxing_object::value_offset_in_bytes(type);
|
||||
switch (type) {
|
||||
case T_BOOLEAN: _jca->push_int(arg->bool_field(box_offset)); break;
|
||||
case T_CHAR: _jca->push_int(arg->char_field(box_offset)); break;
|
||||
case T_SHORT: _jca->push_int(arg->short_field(box_offset)); break;
|
||||
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 {
|
||||
|
|
|
@ -67,7 +67,7 @@ ConstMethod::ConstMethod(int byte_code_size,
|
|||
set_max_locals(0);
|
||||
set_method_idnum(0);
|
||||
set_size_of_parameters(0);
|
||||
set_result_type(T_VOID);
|
||||
set_result_type((BasicType)0);
|
||||
}
|
||||
|
||||
// Accessor that copies to metadata.
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/typeArrayOop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/init.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 {
|
||||
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()) {
|
||||
// have to look at the signature for this one
|
||||
Symbol* constant_type = uncached_signature_ref_at(which);
|
||||
return FieldType::basic_type(constant_type);
|
||||
return Signature::basic_type(constant_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);
|
||||
}
|
||||
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)) {
|
||||
// Make sure the primitive value is properly boxed.
|
||||
// This is a JDK responsibility.
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -114,22 +114,22 @@ class ComputeCallStack : public SignatureIterator {
|
|||
void set(CellTypeState state) { _effect[_idx++] = state; }
|
||||
int length() { return _idx; };
|
||||
|
||||
virtual void do_bool () { set(CellTypeState::value); };
|
||||
virtual void do_char () { set(CellTypeState::value); };
|
||||
virtual void do_float () { set(CellTypeState::value); };
|
||||
virtual void do_byte () { set(CellTypeState::value); };
|
||||
virtual void do_short () { set(CellTypeState::value); };
|
||||
virtual void do_int () { set(CellTypeState::value); };
|
||||
virtual void do_void () { set(CellTypeState::bottom);};
|
||||
virtual void do_object(int begin, int end) { set(CellTypeState::ref); };
|
||||
virtual void do_array (int begin, int end) { set(CellTypeState::ref); };
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type, bool for_return = false) {
|
||||
if (for_return && type == T_VOID) {
|
||||
set(CellTypeState::bottom);
|
||||
} else if (is_reference_type(type)) {
|
||||
set(CellTypeState::ref);
|
||||
} else {
|
||||
assert(is_java_primitive(type), "");
|
||||
set(CellTypeState::value);
|
||||
if (is_double_word_type(type)) {
|
||||
set(CellTypeState::value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_double() { set(CellTypeState::value);
|
||||
set(CellTypeState::value); }
|
||||
void do_long () { set(CellTypeState::value);
|
||||
set(CellTypeState::value); }
|
||||
|
||||
public:
|
||||
public:
|
||||
ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {};
|
||||
|
||||
// Compute methods
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
if (!is_static)
|
||||
effect[_idx++] = CellTypeState::ref;
|
||||
|
||||
iterate_parameters();
|
||||
do_parameters_on(this);
|
||||
|
||||
return length();
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
int compute_for_returntype(CellTypeState *effect) {
|
||||
_idx = 0;
|
||||
_effect = effect;
|
||||
iterate_returntype();
|
||||
do_type(return_type(), true);
|
||||
set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
|
||||
|
||||
return length();
|
||||
|
@ -168,22 +168,22 @@ class ComputeEntryStack : public SignatureIterator {
|
|||
void set(CellTypeState state) { _effect[_idx++] = state; }
|
||||
int length() { return _idx; };
|
||||
|
||||
virtual void do_bool () { set(CellTypeState::value); };
|
||||
virtual void do_char () { set(CellTypeState::value); };
|
||||
virtual void do_float () { set(CellTypeState::value); };
|
||||
virtual void do_byte () { set(CellTypeState::value); };
|
||||
virtual void do_short () { set(CellTypeState::value); };
|
||||
virtual void do_int () { set(CellTypeState::value); };
|
||||
virtual void do_void () { set(CellTypeState::bottom);};
|
||||
virtual void do_object(int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); }
|
||||
virtual void do_array (int begin, int end) { set(CellTypeState::make_slot_ref(_idx)); }
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type, bool for_return = false) {
|
||||
if (for_return && type == T_VOID) {
|
||||
set(CellTypeState::bottom);
|
||||
} else if (is_reference_type(type)) {
|
||||
set(CellTypeState::make_slot_ref(_idx));
|
||||
} else {
|
||||
assert(is_java_primitive(type), "");
|
||||
set(CellTypeState::value);
|
||||
if (is_double_word_type(type)) {
|
||||
set(CellTypeState::value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_double() { set(CellTypeState::value);
|
||||
set(CellTypeState::value); }
|
||||
void do_long () { set(CellTypeState::value);
|
||||
set(CellTypeState::value); }
|
||||
|
||||
public:
|
||||
public:
|
||||
ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {};
|
||||
|
||||
// Compute methods
|
||||
|
@ -194,7 +194,7 @@ public:
|
|||
if (!is_static)
|
||||
effect[_idx++] = CellTypeState::make_slot_ref(0);
|
||||
|
||||
iterate_parameters();
|
||||
do_parameters_on(this);
|
||||
|
||||
return length();
|
||||
};
|
||||
|
@ -202,7 +202,7 @@ public:
|
|||
int compute_for_returntype(CellTypeState *effect) {
|
||||
_idx = 0;
|
||||
_effect = effect;
|
||||
iterate_returntype();
|
||||
do_type(return_type(), true);
|
||||
set(CellTypeState::bottom); // Always terminate with a bottom state, so ppush works
|
||||
|
||||
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);
|
||||
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 *eff = sigchar_to_effect(sigch, bci, temp);
|
||||
CellTypeState *eff = signature_to_effect(signature, bci, temp);
|
||||
|
||||
CellTypeState in[4];
|
||||
CellTypeState *out;
|
||||
|
@ -1991,16 +1987,17 @@ 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...
|
||||
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
|
||||
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[1] = CellTypeState::bottom;
|
||||
return out;
|
||||
}
|
||||
if (sigch == JVM_SIGNATURE_LONG || sigch == JVM_SIGNATURE_DOUBLE) return vvCTS; // Long and Double
|
||||
if (sigch == JVM_SIGNATURE_VOID) return epsilonCTS; // Void
|
||||
return vCTS; // Otherwise
|
||||
if (is_double_word_type(bt)) return vvCTS; // Long and Double
|
||||
if (bt == T_VOID) return epsilonCTS; // Void
|
||||
return vCTS; // Otherwise
|
||||
}
|
||||
|
||||
long GenerateOopMap::_total_byte_count = 0;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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_return_monitor_check ();
|
||||
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);
|
||||
|
||||
// Error handling
|
||||
|
|
|
@ -577,9 +577,16 @@ int Method::extra_stack_words() {
|
|||
return extra_stack_entries() * Interpreter::stackElementSize;
|
||||
}
|
||||
|
||||
void Method::compute_size_of_parameters(Thread *thread) {
|
||||
ArgumentSizeComputer asc(signature());
|
||||
set_size_of_parameters(asc.size() + (is_static() ? 0 : 1));
|
||||
// Derive size of parameters, return type, and fingerprint,
|
||||
// all in one pass, which is run at load time.
|
||||
// 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 {
|
||||
|
@ -1443,9 +1450,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
|
|||
m->set_signature_index(_imcp_invoke_signature);
|
||||
assert(MethodHandles::is_signature_polymorphic_name(m->name()), "");
|
||||
assert(m->signature() == signature, "");
|
||||
ResultTypeFinder rtf(signature);
|
||||
m->constMethod()->set_result_type(rtf.type());
|
||||
m->compute_size_of_parameters(THREAD);
|
||||
m->compute_from_signature(signature);
|
||||
m->init_intrinsic_id();
|
||||
assert(m->is_method_handle_intrinsic(), "");
|
||||
#ifdef ASSERT
|
||||
|
@ -1685,7 +1690,7 @@ bool Method::load_signature_classes(const methodHandle& m, TRAPS) {
|
|||
ResourceMark rm(THREAD);
|
||||
Symbol* signature = m->signature();
|
||||
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
|
||||
if (ss.is_object()) {
|
||||
if (ss.is_reference()) {
|
||||
Symbol* sym = ss.as_symbol();
|
||||
Symbol* name = sym;
|
||||
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();
|
||||
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
|
||||
if (ss.type() == T_OBJECT) {
|
||||
Symbol* name = ss.as_symbol_or_null();
|
||||
if (name == NULL) return true;
|
||||
Symbol* name = ss.as_symbol();
|
||||
Klass* klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
|
||||
if (klass == NULL) return true;
|
||||
}
|
||||
|
@ -1733,7 +1737,7 @@ void Method::print_short_name(outputStream* st) {
|
|||
name()->print_symbol_on(st);
|
||||
if (WizardMode) signature()->print_symbol_on(st);
|
||||
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
|
||||
|
@ -1786,8 +1790,8 @@ class SignatureTypePrinter : public SignatureTypeNames {
|
|||
_use_separator = false;
|
||||
}
|
||||
|
||||
void print_parameters() { _use_separator = false; iterate_parameters(); }
|
||||
void print_returntype() { _use_separator = false; iterate_returntype(); }
|
||||
void print_parameters() { _use_separator = false; do_parameters_on(this); }
|
||||
void print_returntype() { _use_separator = false; do_type(return_type()); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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(); }
|
||||
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)
|
||||
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
|
||||
BasicType result_type() const { return constMethod()->result_type(); }
|
||||
bool is_returning_oop() const { BasicType r = result_type(); return is_reference_type(r); }
|
||||
|
|
|
@ -199,8 +199,8 @@ int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_rec
|
|||
// Parameter profiling include the receiver
|
||||
int args_count = include_receiver ? 1 : 0;
|
||||
ResourceMark rm;
|
||||
SignatureStream ss(signature);
|
||||
args_count += ss.reference_parameter_count();
|
||||
ReferenceArgumentCount rac(signature);
|
||||
args_count += rac.count();
|
||||
args_count = MIN2(args_count, max);
|
||||
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;
|
||||
}
|
||||
|
||||
class ArgumentOffsetComputer : public SignatureInfo {
|
||||
class ArgumentOffsetComputer : public SignatureIterator {
|
||||
private:
|
||||
int _max;
|
||||
int _offset;
|
||||
GrowableArray<int> _offsets;
|
||||
|
||||
void set(int size, BasicType type) { _size += size; }
|
||||
void do_object(int begin, int end) {
|
||||
if (_offsets.length() < _max) {
|
||||
_offsets.push(_size);
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
if (is_reference_type(type) && _offsets.length() < _max) {
|
||||
_offsets.push(_offset);
|
||||
}
|
||||
SignatureInfo::do_object(begin, end);
|
||||
}
|
||||
void do_array (int begin, int end) {
|
||||
if (_offsets.length() < _max) {
|
||||
_offsets.push(_size);
|
||||
}
|
||||
SignatureInfo::do_array(begin, end);
|
||||
_offset += parameter_type_word_count(type);
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
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); }
|
||||
};
|
||||
|
||||
|
@ -266,7 +262,6 @@ void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver,
|
|||
start += 1;
|
||||
}
|
||||
ArgumentOffsetComputer aos(signature, _number_of_entries-start);
|
||||
aos.total();
|
||||
for (int i = start; i < _number_of_entries; i++) {
|
||||
set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
|
||||
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");
|
||||
Bytecode_invoke inv(stream->method(), stream->bci());
|
||||
|
||||
SignatureStream ss(inv.signature());
|
||||
if (has_arguments()) {
|
||||
#ifdef ASSERT
|
||||
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?");
|
||||
check_number_of_arguments(count);
|
||||
#endif
|
||||
|
@ -301,8 +296,8 @@ void VirtualCallTypeData::post_initialize(BytecodeStream* stream, MethodData* md
|
|||
if (has_arguments()) {
|
||||
#ifdef ASSERT
|
||||
ResourceMark rm;
|
||||
SignatureStream ss(inv.signature());
|
||||
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?");
|
||||
check_number_of_arguments(count);
|
||||
#endif
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
_length_and_refcount = pack_length_and_refcount(length, refcount);
|
||||
_identity_hash = (short)os::random();
|
||||
_body[0] = 0; // in case length == 0
|
||||
for (int i = 0; i < length; 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
|
||||
// length.
|
||||
bool Symbol::starts_with(const char* prefix, int len) const {
|
||||
if (len > utf8_length()) return false;
|
||||
while (len-- > 0) {
|
||||
if (prefix[len] != char_at(len))
|
||||
return false;
|
||||
}
|
||||
assert(len == -1, "we should be at the beginning");
|
||||
return true;
|
||||
// Tests if the symbol contains the given byte at the given position.
|
||||
bool Symbol::contains_byte_at(int position, char code_byte) const {
|
||||
if (position < 0) return false; // can happen with ends_with
|
||||
if (position >= utf8_length()) return false;
|
||||
return code_byte == char_at(position);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// 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
|
||||
|
@ -116,8 +128,11 @@ int Symbol::index_of_at(int i, const char* str, int len) const {
|
|||
if (scan == NULL)
|
||||
return -1; // not found
|
||||
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 -1;
|
||||
}
|
||||
|
@ -186,8 +201,8 @@ const char* Symbol::as_klass_external_name(char* buf, int size) const {
|
|||
int length = (int)strlen(str);
|
||||
// Turn all '/'s into '.'s (also for array klasses)
|
||||
for (int index = 0; index < length; index++) {
|
||||
if (str[index] == '/') {
|
||||
str[index] = '.';
|
||||
if (str[index] == JVM_SIGNATURE_SLASH) {
|
||||
str[index] = JVM_SIGNATURE_DOT;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
|
@ -208,28 +223,25 @@ const char* Symbol::as_klass_external_name() const {
|
|||
return str;
|
||||
}
|
||||
|
||||
static void print_class(outputStream *os, char *class_str, int len) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (class_str[i] == JVM_SIGNATURE_SLASH) {
|
||||
static void print_class(outputStream *os, const SignatureStream& ss) {
|
||||
int sb = ss.raw_symbol_begin(), se = ss.raw_symbol_end();
|
||||
for (int i = sb; i < se; ++i) {
|
||||
int ch = ss.raw_char_at(i);
|
||||
if (ch == JVM_SIGNATURE_SLASH) {
|
||||
os->put(JVM_SIGNATURE_DOT);
|
||||
} else {
|
||||
os->put(class_str[i]);
|
||||
os->put(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_array(outputStream *os, char *array_str, int len) {
|
||||
int dimensions = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (array_str[i] == JVM_SIGNATURE_ARRAY) {
|
||||
dimensions++;
|
||||
} 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 {
|
||||
os->print("%s", type2name(char2type(array_str[i])));
|
||||
}
|
||||
static void print_array(outputStream *os, SignatureStream& ss) {
|
||||
int dimensions = ss.skip_array_prefix();
|
||||
assert(dimensions > 0, "");
|
||||
if (ss.is_reference()) {
|
||||
print_class(os, ss);
|
||||
} else {
|
||||
os->print("%s", type2name(ss.type()));
|
||||
}
|
||||
for (int i = 0; i < dimensions; ++i) {
|
||||
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()) {
|
||||
if (ss.at_return_type()) {
|
||||
if (ss.is_array()) {
|
||||
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
|
||||
} else if (ss.is_object()) {
|
||||
// Expected format: L<type name>;. Skip 'L' and ';' delimiting the class name.
|
||||
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
|
||||
print_array(os, ss);
|
||||
} else if (ss.is_reference()) {
|
||||
print_class(os, ss);
|
||||
} else {
|
||||
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 (!first) { os->print(", "); }
|
||||
if (ss.is_array()) {
|
||||
print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
|
||||
} else if (ss.is_object()) {
|
||||
// Skip 'L' and ';'.
|
||||
print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
|
||||
print_array(os, ss);
|
||||
} else if (ss.is_reference()) {
|
||||
print_class(os, ss);
|
||||
} else {
|
||||
os->print("%s", type2name(ss.type()));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 {
|
||||
int l = utf8_length();
|
||||
if (l != len) return false;
|
||||
while (l-- > 0) {
|
||||
if (str[l] != char_at(l))
|
||||
return false;
|
||||
}
|
||||
assert(l == -1, "we should be at the beginning");
|
||||
return true;
|
||||
return contains_utf8_at(0, str, len);
|
||||
}
|
||||
bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
|
||||
|
||||
// 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 {
|
||||
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.
|
||||
int index_of_at(int i, const char* str, int len) const;
|
||||
|
|
|
@ -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.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
|
@ -862,40 +862,29 @@ class JNI_ArgumentPusher : public SignatureIterator {
|
|||
protected:
|
||||
JavaCallArguments* _arguments;
|
||||
|
||||
virtual void get_bool () = 0;
|
||||
virtual void get_char () = 0;
|
||||
virtual void get_short () = 0;
|
||||
virtual void get_byte () = 0;
|
||||
virtual void get_int () = 0;
|
||||
virtual void get_long () = 0;
|
||||
virtual void get_float () = 0;
|
||||
virtual void get_double () = 0;
|
||||
virtual void get_object () = 0;
|
||||
void push_int(jint x) { _arguments->push_int(x); }
|
||||
void push_long(jlong x) { _arguments->push_long(x); }
|
||||
void push_float(jfloat x) { _arguments->push_float(x); }
|
||||
void push_double(jdouble x) { _arguments->push_double(x); }
|
||||
void push_object(jobject x) { _arguments->push_jobject(x); }
|
||||
|
||||
JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) {
|
||||
this->_return_type = T_ILLEGAL;
|
||||
void push_boolean(jboolean b) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void iterate( uint64_t fingerprint ) = 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); }
|
||||
virtual void push_arguments_on(JavaCallArguments* arguments) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -903,90 +892,43 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
|
|||
protected:
|
||||
va_list _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 = 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) {
|
||||
void set_ap(va_list rap) {
|
||||
va_copy(_ap, rap);
|
||||
}
|
||||
|
||||
public:
|
||||
JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)
|
||||
: JNI_ArgumentPusher(signature) {
|
||||
set_ap(rap);
|
||||
}
|
||||
JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
|
||||
: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
|
||||
set_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;
|
||||
|
||||
// Optimized path if we have the bitvector form of signature
|
||||
void iterate( uint64_t fingerprint ) {
|
||||
if (fingerprint == (uint64_t)CONST64(-1)) {
|
||||
SignatureIterator::iterate(); // Must be too many arguments
|
||||
} else {
|
||||
_return_type = (BasicType)((fingerprint >> static_feature_size) &
|
||||
result_feature_mask);
|
||||
// each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
|
||||
|
||||
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;
|
||||
}
|
||||
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:
|
||||
JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
|
||||
: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
|
||||
set_ap(rap);
|
||||
}
|
||||
|
||||
virtual void push_arguments_on(JavaCallArguments* arguments) {
|
||||
_arguments = arguments;
|
||||
do_parameters_on(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -994,84 +936,34 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
|
|||
protected:
|
||||
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; }
|
||||
|
||||
public:
|
||||
JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap)
|
||||
: JNI_ArgumentPusher(signature) {
|
||||
set_ap(rap);
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
switch (type) {
|
||||
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_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
|
||||
: JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
|
||||
set_ap(rap);
|
||||
}
|
||||
|
||||
// Optimized path if we have the bitvector form of signature
|
||||
void iterate( uint64_t fingerprint ) {
|
||||
if (fingerprint == (uint64_t)CONST64(-1)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
virtual void push_arguments_on(JavaCallArguments* arguments) {
|
||||
_arguments = arguments;
|
||||
do_parameters_on(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1092,14 +984,13 @@ static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver,
|
|||
ResourceMark rm(THREAD);
|
||||
int number_of_parameters = method->size_of_parameters();
|
||||
JavaCallArguments java_args(number_of_parameters);
|
||||
args->set_java_argument_object(&java_args);
|
||||
|
||||
assert(method->is_static(), "method should be static");
|
||||
|
||||
// Fill out JavaCallArguments object
|
||||
args->iterate( Fingerprinter(method).fingerprint() );
|
||||
args->push_arguments_on(&java_args);
|
||||
// Initialize result type
|
||||
result->set_type(args->get_ret_type());
|
||||
result->set_type(args->return_type());
|
||||
|
||||
// Invoke the method. Result is returned as oop.
|
||||
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
|
||||
ResourceMark rm(THREAD);
|
||||
JavaCallArguments java_args(number_of_parameters);
|
||||
args->set_java_argument_object(&java_args);
|
||||
|
||||
// handle arguments
|
||||
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
|
||||
args->iterate( Fingerprinter(method).fingerprint() );
|
||||
args->push_arguments_on(&java_args);
|
||||
// Initialize result type
|
||||
result->set_type(args->get_ret_type());
|
||||
result->set_type(args->return_type());
|
||||
|
||||
// Invoke the method. Result is returned as oop.
|
||||
JavaCalls::call(result, method, &java_args, CHECK);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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
|
||||
}
|
||||
Symbol* sign_sym = method_oop->constants()->symbol_at(signature_idx);
|
||||
const char* signature = (const char *) sign_sym->as_utf8();
|
||||
BasicType slot_type = char2type(signature[0]);
|
||||
BasicType slot_type = Signature::basic_type(sign_sym);
|
||||
|
||||
switch (slot_type) {
|
||||
case T_BYTE:
|
||||
|
@ -602,6 +601,7 @@ bool VM_GetOrSetLocal::check_slot_type_lvt(javaVFrame* jvf) {
|
|||
Klass* ob_k = obj->klass();
|
||||
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)) {
|
||||
_result = JVMTI_ERROR_TYPE_MISMATCH;
|
||||
return false;
|
||||
|
|
|
@ -539,25 +539,21 @@ enum { OBJ_SIG_LEN = 18 };
|
|||
bool MethodHandles::is_basic_type_signature(Symbol* sig) {
|
||||
assert(vmSymbols::object_signature()->utf8_length() == (int)OBJ_SIG_LEN, "");
|
||||
assert(vmSymbols::object_signature()->equals(OBJ_SIG), "");
|
||||
const int len = sig->utf8_length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
switch (sig->char_at(i)) {
|
||||
case JVM_SIGNATURE_CLASS:
|
||||
for (SignatureStream ss(sig, sig->starts_with(JVM_SIGNATURE_FUNC)); !ss.is_done(); ss.next()) {
|
||||
switch (ss.type()) {
|
||||
case T_OBJECT:
|
||||
// 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;
|
||||
i += OBJ_SIG_LEN-1; //-1 because of i++ in loop
|
||||
continue;
|
||||
case JVM_SIGNATURE_FUNC:
|
||||
case JVM_SIGNATURE_ENDFUNC:
|
||||
case JVM_SIGNATURE_VOID:
|
||||
case JVM_SIGNATURE_INT:
|
||||
case JVM_SIGNATURE_LONG:
|
||||
case JVM_SIGNATURE_FLOAT:
|
||||
case JVM_SIGNATURE_DOUBLE:
|
||||
continue;
|
||||
break;
|
||||
case T_VOID:
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE:
|
||||
break;
|
||||
default:
|
||||
// subword types (T_BYTE etc.), arrays
|
||||
// subword types (T_BYTE etc.), Q-descriptors, arrays
|
||||
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)) {
|
||||
sig->increment_refcount();
|
||||
return sig; // that was easy
|
||||
} else if (sig->char_at(0) != JVM_SIGNATURE_FUNC) {
|
||||
BasicType bt = char2type(sig->char_at(0));
|
||||
} else if (!sig->starts_with(JVM_SIGNATURE_FUNC)) {
|
||||
BasicType bt = Signature::basic_type(sig);
|
||||
if (is_subword_type(bt)) {
|
||||
bsig = vmSymbols::int_signature();
|
||||
} 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,
|
||||
Symbol* sig,
|
||||
bool keep_arrays,
|
||||
bool keep_basic_names) {
|
||||
Symbol* sig) {
|
||||
st = st ? st : tty;
|
||||
int len = sig->utf8_length();
|
||||
int array = 0;
|
||||
bool prev_type = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char ch = sig->char_at(i);
|
||||
switch (ch) {
|
||||
case JVM_SIGNATURE_FUNC:
|
||||
case JVM_SIGNATURE_ENDFUNC:
|
||||
prev_type = false;
|
||||
st->put(ch);
|
||||
continue;
|
||||
case JVM_SIGNATURE_ARRAY:
|
||||
if (!keep_basic_names && keep_arrays)
|
||||
st->put(ch);
|
||||
array++;
|
||||
continue;
|
||||
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);
|
||||
} else {
|
||||
for (int j = start; j < i; j++)
|
||||
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;
|
||||
}
|
||||
bool is_method = (sig->char_at(0) == JVM_SIGNATURE_FUNC);
|
||||
if (is_method) st->put(JVM_SIGNATURE_FUNC);
|
||||
for (SignatureStream ss(sig, is_method); !ss.is_done(); ss.next()) {
|
||||
if (ss.at_return_type())
|
||||
st->put(JVM_SIGNATURE_ENDFUNC);
|
||||
else if (prev_type)
|
||||
st->put(',');
|
||||
const char* cp = (const char*) ss.raw_bytes();
|
||||
if (ss.is_array()) {
|
||||
st->put(JVM_SIGNATURE_ARRAY);
|
||||
if (ss.array_prefix_length() == 1)
|
||||
st->put(cp[1]);
|
||||
else
|
||||
st->put(JVM_SIGNATURE_CLASS);
|
||||
} else {
|
||||
st->put(cp[0]);
|
||||
}
|
||||
// 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) {
|
||||
if (s == NULL) return NULL;
|
||||
BasicType bt = FieldType::basic_type(s);
|
||||
BasicType bt = Signature::basic_type(s);
|
||||
if (is_java_primitive(bt)) {
|
||||
assert(s->utf8_length() == 1, "");
|
||||
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 (sig != NULL) {
|
||||
if (sig->utf8_length() == 0) return 0; // a match is not possible
|
||||
if (sig->char_at(0) == JVM_SIGNATURE_FUNC)
|
||||
if (sig->starts_with(JVM_SIGNATURE_FUNC))
|
||||
match_flags &= ~(IS_FIELD | IS_TYPE);
|
||||
else
|
||||
match_flags &= ~(IS_CONSTRUCTOR | IS_METHOD);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 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
|
||||
enum { JVM_REF_MIN = JVM_REF_getField, JVM_REF_MAX = JVM_REF_invokeInterface };
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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())) {
|
||||
ReassignedField field;
|
||||
field._offset = fs.offset();
|
||||
field._type = FieldType::basic_type(fs.signature());
|
||||
field._type = Signature::basic_type(fs.signature());
|
||||
fields->append(field);
|
||||
}
|
||||
}
|
||||
|
@ -1606,33 +1606,20 @@ Deoptimization::get_method_data(JavaThread* thread, const methodHandle& m,
|
|||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
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()) {
|
||||
Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!constant_pool->tag_at(index).is_symbol()) return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
assert(!constant_pool->tag_at(index).is_symbol(),
|
||||
"no symbolic names here, please");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -29,7 +29,6 @@
|
|||
#include "oops/fieldInfo.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "runtime/fieldType.hpp"
|
||||
#include "utilities/accessFlags.hpp"
|
||||
#include "utilities/constantTag.hpp"
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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 {
|
||||
return FieldType::basic_type(signature());
|
||||
return Signature::basic_type(signature());
|
||||
}
|
||||
|
||||
#endif // SHARE_RUNTIME_FIELDDESCRIPTOR_INLINE_HPP
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -714,17 +714,18 @@ class InterpreterFrameClosure : public OffsetClosure {
|
|||
};
|
||||
|
||||
|
||||
class InterpretedArgumentOopFinder: public SignatureInfo {
|
||||
class InterpretedArgumentOopFinder: public SignatureIterator {
|
||||
private:
|
||||
OopClosure* _f; // Closure to invoke
|
||||
int _offset; // TOS-relative offset, decremented with each argument
|
||||
bool _has_receiver; // true if the callee has a receiver
|
||||
frame* _fr;
|
||||
|
||||
void set(int size, BasicType type) {
|
||||
_offset -= size;
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
_offset -= parameter_type_word_count(type);
|
||||
if (is_reference_type(type)) oop_offset_do();
|
||||
}
|
||||
}
|
||||
|
||||
void oop_offset_do() {
|
||||
oop* addr;
|
||||
|
@ -733,7 +734,7 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
|
|||
}
|
||||
|
||||
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
|
||||
int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0);
|
||||
assert(!fr->is_interpreted_frame() ||
|
||||
|
@ -750,7 +751,7 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
|
|||
--_offset;
|
||||
oop_offset_do();
|
||||
}
|
||||
iterate_parameters();
|
||||
do_parameters_on(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -767,18 +768,20 @@ class InterpretedArgumentOopFinder: public SignatureInfo {
|
|||
|
||||
|
||||
// visits and GC's all the arguments in entry frame
|
||||
class EntryFrameOopFinder: public SignatureInfo {
|
||||
class EntryFrameOopFinder: public SignatureIterator {
|
||||
private:
|
||||
bool _is_static;
|
||||
int _offset;
|
||||
frame* _fr;
|
||||
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");
|
||||
if (is_reference_type(type)) oop_at_offset_do(_offset);
|
||||
_offset -= size;
|
||||
}
|
||||
if (is_reference_type(type)) oop_at_offset_do(_offset);
|
||||
}
|
||||
|
||||
void oop_at_offset_do(int offset) {
|
||||
assert (offset >= 0, "illegal offset");
|
||||
|
@ -787,17 +790,17 @@ class EntryFrameOopFinder: public SignatureInfo {
|
|||
}
|
||||
|
||||
public:
|
||||
EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureInfo(signature) {
|
||||
_f = NULL; // will be set later
|
||||
_fr = frame;
|
||||
_is_static = is_static;
|
||||
_offset = ArgumentSizeComputer(signature).size() - 1; // last parameter is at index 0
|
||||
}
|
||||
EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureIterator(signature) {
|
||||
_f = NULL; // will be set later
|
||||
_fr = frame;
|
||||
_is_static = is_static;
|
||||
_offset = ArgumentSizeComputer(signature).size(); // pre-decremented down to zero
|
||||
}
|
||||
|
||||
void arguments_do(OopClosure* f) {
|
||||
_f = f;
|
||||
if (!_is_static) oop_at_offset_do(_offset+1); // do the receiver
|
||||
iterate_parameters();
|
||||
if (!_is_static) oop_at_offset_do(_offset); // do the receiver
|
||||
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);
|
||||
}
|
||||
|
||||
class CompiledArgumentOopFinder: public SignatureInfo {
|
||||
class CompiledArgumentOopFinder: public SignatureIterator {
|
||||
protected:
|
||||
OopClosure* _f;
|
||||
int _offset; // the current offset, incremented with each argument
|
||||
|
@ -926,9 +929,10 @@ class CompiledArgumentOopFinder: public SignatureInfo {
|
|||
int _arg_size;
|
||||
VMRegPair* _regs; // VMReg list of arguments
|
||||
|
||||
void set(int size, BasicType type) {
|
||||
if (is_reference_type(type)) handle_oop_offset();
|
||||
_offset += size;
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
if (is_reference_type(type)) handle_oop_offset();
|
||||
_offset += parameter_type_word_count(type);
|
||||
}
|
||||
|
||||
virtual void handle_oop_offset() {
|
||||
|
@ -940,8 +944,8 @@ class CompiledArgumentOopFinder: public SignatureInfo {
|
|||
}
|
||||
|
||||
public:
|
||||
CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map)
|
||||
: SignatureInfo(signature) {
|
||||
CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, bool has_appendix, OopClosure* f, frame fr, const RegisterMap* reg_map)
|
||||
: SignatureIterator(signature) {
|
||||
|
||||
// initialize CompiledArgumentOopFinder
|
||||
_f = f;
|
||||
|
@ -962,7 +966,7 @@ class CompiledArgumentOopFinder: public SignatureInfo {
|
|||
handle_oop_offset();
|
||||
_offset++;
|
||||
}
|
||||
iterate_parameters();
|
||||
do_parameters_on(this);
|
||||
if (_has_appendix) {
|
||||
handle_oop_offset();
|
||||
_offset++;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -521,8 +521,6 @@ class SignatureChekker : public SignatureIterator {
|
|||
intptr_t* _value;
|
||||
|
||||
public:
|
||||
bool _is_return;
|
||||
|
||||
SignatureChekker(Symbol* signature,
|
||||
BasicType return_type,
|
||||
bool is_static,
|
||||
|
@ -532,17 +530,19 @@ class SignatureChekker : public SignatureIterator {
|
|||
_pos(0),
|
||||
_return_type(return_type),
|
||||
_value_state(value_state),
|
||||
_value(value),
|
||||
_is_return(false)
|
||||
_value(value)
|
||||
{
|
||||
if (!is_static) {
|
||||
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++];
|
||||
if (type) {
|
||||
if (is_reference) {
|
||||
guarantee(is_value_state_indirect_oop(state),
|
||||
"signature does not match pushed arguments: %u at %d",
|
||||
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) {
|
||||
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) {
|
||||
if (_is_return) {
|
||||
check_return_type(t);
|
||||
return;
|
||||
}
|
||||
void check_single_word() {
|
||||
check_value(false);
|
||||
}
|
||||
|
||||
void check_double(BasicType t) { check_long(t); }
|
||||
|
||||
void check_long(BasicType t) {
|
||||
if (_is_return) {
|
||||
check_return_type(t);
|
||||
return;
|
||||
}
|
||||
|
||||
void check_double_word() {
|
||||
check_value(false);
|
||||
check_value(false);
|
||||
}
|
||||
|
||||
void check_obj(BasicType t) {
|
||||
if (_is_return) {
|
||||
check_return_type(t);
|
||||
return;
|
||||
}
|
||||
|
||||
void check_reference() {
|
||||
intptr_t v = _value[_pos];
|
||||
if (v != 0) {
|
||||
// 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.
|
||||
}
|
||||
|
||||
void do_bool() { check_int(T_BOOLEAN); }
|
||||
void do_char() { check_int(T_CHAR); }
|
||||
void do_float() { check_int(T_FLOAT); }
|
||||
void do_double() { check_double(T_DOUBLE); }
|
||||
void do_byte() { check_int(T_BYTE); }
|
||||
void do_short() { check_int(T_SHORT); }
|
||||
void do_int() { check_int(T_INT); }
|
||||
void do_long() { check_long(T_LONG); }
|
||||
void do_void() { check_return_type(T_VOID); }
|
||||
void do_object(int begin, int end) { check_obj(T_OBJECT); }
|
||||
void do_array(int begin, int end) { check_obj(T_OBJECT); }
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
switch (type) {
|
||||
case T_BYTE:
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_SHORT:
|
||||
case T_INT:
|
||||
case T_FLOAT: // this one also
|
||||
check_single_word(); break;
|
||||
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(),
|
||||
_value_state,
|
||||
_value);
|
||||
sc.iterate_parameters();
|
||||
sc.check_doing_return(true);
|
||||
sc.iterate_returntype();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
SignatureStream ss(signature, false);
|
||||
// Basic types
|
||||
BasicType type = vmSymbols::signature_type(signature);
|
||||
BasicType type = ss.is_reference() ? T_OBJECT : ss.type();
|
||||
if (type != T_OBJECT) {
|
||||
return Handle(THREAD, Universe::java_mirror(type));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* 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) {
|
||||
// This method is returning a data structure allocating as a
|
||||
// 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);
|
||||
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
|
||||
}
|
||||
|
||||
while (*s != JVM_SIGNATURE_ENDFUNC) { // Find closing right paren
|
||||
switch (*s++) { // Switch on signature character
|
||||
case JVM_SIGNATURE_BYTE: sig_bt[cnt++] = T_BYTE; break;
|
||||
case JVM_SIGNATURE_CHAR: sig_bt[cnt++] = T_CHAR; break;
|
||||
case JVM_SIGNATURE_DOUBLE: sig_bt[cnt++] = T_DOUBLE; sig_bt[cnt++] = T_VOID; break;
|
||||
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();
|
||||
}
|
||||
for (SignatureStream ss(sig); !ss.at_return_type(); ss.next()) {
|
||||
BasicType type = ss.type();
|
||||
sig_bt[cnt++] = type;
|
||||
if (is_double_word_type(type))
|
||||
sig_bt[cnt++] = T_VOID;
|
||||
}
|
||||
|
||||
if (has_appendix) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -32,6 +32,9 @@
|
|||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "oops/typeArrayKlass.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
|
||||
// Implementation of SignatureIterator
|
||||
|
@ -44,232 +47,154 @@
|
|||
// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
|
||||
// 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) {
|
||||
_signature = signature;
|
||||
_parameter_index = 0;
|
||||
}
|
||||
|
||||
void SignatureIterator::expect(char c) {
|
||||
if (_signature->char_at(_index) != c) fatal("expecting %c", c);
|
||||
_index++;
|
||||
}
|
||||
|
||||
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);
|
||||
void SignatureIterator::set_fingerprint(fingerprint_t fingerprint) {
|
||||
if (!fp_is_valid(fingerprint)) {
|
||||
_fingerprint = fingerprint;
|
||||
_return_type = T_ILLEGAL;
|
||||
} else if (fingerprint != _fingerprint) {
|
||||
assert(_fingerprint == zero_fingerprint(), "consistent fingerprint values");
|
||||
_fingerprint = fingerprint;
|
||||
_return_type = fp_return_type(fingerprint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignatureIterator::iterate_parameters() {
|
||||
// Parse parameters
|
||||
_index = 0;
|
||||
_parameter_index = 0;
|
||||
expect(JVM_SIGNATURE_FUNC);
|
||||
while (_signature->char_at(_index) != JVM_SIGNATURE_ENDFUNC) _parameter_index += parse_type();
|
||||
expect(JVM_SIGNATURE_ENDFUNC);
|
||||
_parameter_index = 0;
|
||||
BasicType SignatureIterator::return_type() {
|
||||
if (_return_type == T_ILLEGAL) {
|
||||
SignatureStream ss(_signature);
|
||||
ss.skip_to_return_type();
|
||||
_return_type = ss.type();
|
||||
assert(_return_type != T_ILLEGAL, "illegal return type");
|
||||
}
|
||||
return _return_type;
|
||||
}
|
||||
|
||||
// Optimized version of iterate_parameters when fingerprint is known
|
||||
void SignatureIterator::iterate_parameters( uint64_t fingerprint ) {
|
||||
uint64_t saved_fingerprint = fingerprint;
|
||||
bool SignatureIterator::fp_is_valid_type(BasicType type, bool for_return_type) {
|
||||
assert(type != (BasicType)fp_parameters_done, "fingerprint is incorrectly at done");
|
||||
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
|
||||
if (fingerprint == (uint64_t)CONST64(-1)) {
|
||||
SignatureIterator::iterate_parameters();
|
||||
ArgumentSizeComputer::ArgumentSizeComputer(Symbol* signature)
|
||||
: SignatureIterator(signature)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
if (_method->size_of_parameters() > fp_max_size_of_parameters) {
|
||||
_fingerprint = overflow_fingerprint();
|
||||
_method->constMethod()->set_fingerprint(_fingerprint);
|
||||
// as long as we are here compute the return type:
|
||||
_return_type = ResultTypeFinder(_method->signature()).type();
|
||||
assert(is_java_type(_return_type), "return type must be a java type");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
// Fill in the return type and static bits:
|
||||
_accumulator |= _return_type << fp_static_feature_size;
|
||||
if (static_flag) {
|
||||
_accumulator |= fp_is_static_bit;
|
||||
} else {
|
||||
_param_size += 1; // this is the convention for Method::compute_size_of_parameters
|
||||
}
|
||||
|
||||
// Detect overflow. (We counted _param_size correctly.)
|
||||
if (_method == NULL && _param_size > fp_max_size_of_parameters) {
|
||||
// We did a one-pass computation of argument size, return type,
|
||||
// and fingerprint.
|
||||
_fingerprint = overflow_fingerprint();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(fingerprint, "Fingerprint should not be 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");
|
||||
|
||||
_parameter_index = 0;
|
||||
fingerprint = fingerprint >> (static_feature_size + result_feature_size);
|
||||
while ( 1 ) {
|
||||
switch ( fingerprint & parameter_feature_mask ) {
|
||||
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;
|
||||
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;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SignatureIterator::iterate_returntype() {
|
||||
// Ignore parameters
|
||||
_index = 0;
|
||||
expect(JVM_SIGNATURE_FUNC);
|
||||
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 {
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(JVM_SIGNATURE_ENDFUNC);
|
||||
// Parse return type
|
||||
_parameter_index = -1;
|
||||
parse_type();
|
||||
check_signature_end();
|
||||
_parameter_index = 0;
|
||||
}
|
||||
|
||||
|
||||
void SignatureIterator::iterate() {
|
||||
// Parse parameters
|
||||
_parameter_index = 0;
|
||||
_index = 0;
|
||||
expect(JVM_SIGNATURE_FUNC);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of SignatureStream
|
||||
SignatureStream::SignatureStream(Symbol* signature, bool is_method) :
|
||||
_signature(signature), _at_return_type(false), _previous_name(NULL), _names(NULL) {
|
||||
_begin = _end = (is_method ? 1 : 0); // skip first '(' in method signatures
|
||||
|
||||
static inline int decode_signature_char(int ch) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -279,84 +204,162 @@ SignatureStream::~SignatureStream() {
|
|||
for (int i = 0; i < _names->length(); i++) {
|
||||
_names->at(i)->decrement_refcount();
|
||||
}
|
||||
} else if (_previous_name != NULL && !_previous_name->is_permanent()) {
|
||||
_previous_name->decrement_refcount();
|
||||
}
|
||||
}
|
||||
|
||||
bool SignatureStream::is_done() const {
|
||||
return _end > _signature->utf8_length();
|
||||
}
|
||||
inline int SignatureStream::scan_non_primitive(BasicType type) {
|
||||
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;
|
||||
|
||||
|
||||
void SignatureStream::next_non_primitive(int t) {
|
||||
switch (t) {
|
||||
case JVM_SIGNATURE_CLASS: {
|
||||
_type = T_OBJECT;
|
||||
Symbol* sig = _signature;
|
||||
while (sig->char_at(_end++) != JVM_SIGNATURE_ENDCLASS);
|
||||
case T_ARRAY:
|
||||
while ((end < limit) && ((char)base[end] == JVM_SIGNATURE_ARRAY)) { end++; }
|
||||
_array_prefix = end - _end; // number of '[' chars just skipped
|
||||
if (Signature::has_envelope(base[end++])) {
|
||||
tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end);
|
||||
end = (tem == NULL ? limit : tem+1 - base);
|
||||
break;
|
||||
}
|
||||
case JVM_SIGNATURE_ARRAY: {
|
||||
_type = T_ARRAY;
|
||||
Symbol* sig = _signature;
|
||||
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)) {
|
||||
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:_end++; break;
|
||||
default: {
|
||||
while (sig->char_at(_end++) != JVM_SIGNATURE_ENDCLASS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JVM_SIGNATURE_ENDFUNC: _end++; next(); _at_return_type = true; break;
|
||||
default : ShouldNotReachHere();
|
||||
break;
|
||||
|
||||
default : ShouldNotReachHere();
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
|
||||
bool SignatureStream::is_object() const {
|
||||
return _type == T_OBJECT
|
||||
|| _type == T_ARRAY;
|
||||
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);
|
||||
}
|
||||
|
||||
bool SignatureStream::is_array() const {
|
||||
return _type == T_ARRAY;
|
||||
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;
|
||||
}
|
||||
|
||||
Symbol* SignatureStream::as_symbol() {
|
||||
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_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:
|
||||
// If it is an array, the type is the last character
|
||||
return (i + 1 == len);
|
||||
case JVM_SIGNATURE_CLASS:
|
||||
// If it is an object, the last character must be a ';'
|
||||
return sig->char_at(len - 1) == JVM_SIGNATURE_ENDCLASS;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType Signature::basic_type(int ch) {
|
||||
int btcode = decode_signature_char(ch);
|
||||
if (btcode == 0) return T_ILLEGAL;
|
||||
return (BasicType) btcode;
|
||||
}
|
||||
|
||||
static const int jl_len = 10, object_len = 6, jl_object_len = jl_len + object_len;
|
||||
static const char jl_str[] = "java/lang/";
|
||||
|
||||
#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
|
||||
int begin = _begin;
|
||||
int end = _end;
|
||||
|
||||
if ( _signature->char_at(_begin) == JVM_SIGNATURE_CLASS
|
||||
&& _signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS) {
|
||||
begin++;
|
||||
end--;
|
||||
}
|
||||
int begin = raw_symbol_begin();
|
||||
int end = raw_symbol_end();
|
||||
|
||||
const char* symbol_chars = (const char*)_signature->base() + begin;
|
||||
int len = end - begin;
|
||||
|
||||
// Quick check for common symbols in signatures
|
||||
assert((vmSymbols::java_lang_String()->utf8_length() == 16 && vmSymbols::java_lang_Object()->utf8_length() == 16), "sanity");
|
||||
if (len == 16 &&
|
||||
strncmp(symbol_chars, "java/lang/", 10) == 0) {
|
||||
if (strncmp("String", symbol_chars + 10, 6) == 0) {
|
||||
assert(signature_symbols_sane(), "incorrect signature sanity check");
|
||||
if (len == jl_object_len &&
|
||||
memcmp(symbol_chars, jl_str, jl_len) == 0) {
|
||||
if (memcmp("String", symbol_chars + jl_len, object_len) == 0) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -369,7 +372,17 @@ Symbol* SignatureStream::as_symbol() {
|
|||
// Save names for cleaning up reference count at the end of
|
||||
// SignatureStream scope.
|
||||
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) {
|
||||
_names = new GrowableArray<Symbol*>(10);
|
||||
}
|
||||
|
@ -381,57 +394,67 @@ Symbol* SignatureStream::as_symbol() {
|
|||
|
||||
Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
if (!is_object()) return NULL;
|
||||
if (!is_reference()) return NULL;
|
||||
Symbol* name = as_symbol();
|
||||
Klass* k = NULL;
|
||||
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 {
|
||||
// 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);
|
||||
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,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
if (!is_object())
|
||||
if (!is_reference())
|
||||
return Universe::java_mirror(type());
|
||||
Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
|
||||
if (klass == NULL) return NULL;
|
||||
return klass->java_mirror();
|
||||
}
|
||||
|
||||
Symbol* SignatureStream::as_symbol_or_null() {
|
||||
// Create a symbol from for string _begin _end
|
||||
ResourceMark rm;
|
||||
|
||||
int begin = _begin;
|
||||
int end = _end;
|
||||
|
||||
if ( _signature->char_at(_begin) == JVM_SIGNATURE_CLASS
|
||||
&& _signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS) {
|
||||
begin++;
|
||||
end--;
|
||||
void SignatureStream::skip_to_return_type() {
|
||||
while (!at_return_type()) {
|
||||
next();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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) {
|
||||
const char* method_sig = (const char*)sig->bytes();
|
||||
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]) {
|
||||
case JVM_SIGNATURE_BYTE:
|
||||
case JVM_SIGNATURE_CHAR:
|
||||
case JVM_SIGNATURE_DOUBLE:
|
||||
case JVM_SIGNATURE_FLOAT:
|
||||
case JVM_SIGNATURE_DOUBLE:
|
||||
case JVM_SIGNATURE_INT:
|
||||
case JVM_SIGNATURE_LONG:
|
||||
case JVM_SIGNATURE_SHORT:
|
||||
|
@ -500,4 +523,5 @@ ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // ASSERT
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,102 +25,232 @@
|
|||
#ifndef SHARE_RUNTIME_SIGNATURE_HPP
|
||||
#define SHARE_RUNTIME_SIGNATURE_HPP
|
||||
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/method.hpp"
|
||||
|
||||
// SignatureIterators iterate over a Java signature (or parts of it).
|
||||
// (Syntax according to: "The Java Virtual Machine Specification" by
|
||||
// Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.)
|
||||
|
||||
// Static routines and parsing loops for processing field and method
|
||||
// descriptors. In the HotSpot sources we call them "signatures".
|
||||
//
|
||||
// Example: Iterating over ([Lfoo;D)I using
|
||||
// 0123456789
|
||||
// A SignatureStream iterates over a Java descriptor (or parts of it).
|
||||
// The syntax is documented in the Java Virtual Machine Specification,
|
||||
// section 4.3.
|
||||
//
|
||||
// iterate_parameters() calls: do_array(2, 7); do_double();
|
||||
// iterate_returntype() calls: do_int();
|
||||
// iterate() calls: do_array(2, 7); do_double(); do_int();
|
||||
// The syntax may be summarized as follows:
|
||||
//
|
||||
// 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
|
||||
// iterator implemented in opto/type.cpp, TypeTuple::make().
|
||||
// All of the concrete characters in the above grammar are given
|
||||
// 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 {
|
||||
public:
|
||||
typedef uint64_t fingerprint_t;
|
||||
|
||||
protected:
|
||||
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;
|
||||
|
||||
void expect(char c);
|
||||
int parse_type(); // returns the parameter size in words (0 for void)
|
||||
void check_signature_end();
|
||||
fingerprint_t _fingerprint;
|
||||
|
||||
public:
|
||||
// Definitions used in generating and iterating the
|
||||
// bit field form of the signature generated by the
|
||||
// Fingerprinter.
|
||||
enum {
|
||||
static_feature_size = 1,
|
||||
is_static_bit = 1,
|
||||
fp_static_feature_size = 1,
|
||||
fp_is_static_bit = 1,
|
||||
|
||||
result_feature_size = 4,
|
||||
result_feature_mask = 0xF,
|
||||
parameter_feature_size = 4,
|
||||
parameter_feature_mask = 0xF,
|
||||
fp_result_feature_size = 4,
|
||||
fp_result_feature_mask = right_n_bits(fp_result_feature_size),
|
||||
fp_parameter_feature_size = 4,
|
||||
fp_parameter_feature_mask = right_n_bits(fp_parameter_feature_size),
|
||||
|
||||
bool_parm = 1,
|
||||
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
|
||||
fp_parameters_done = 0, // marker for end of parameters (must be zero)
|
||||
|
||||
// max parameters is wordsize minus
|
||||
// The sign bit, termination field, the result and static bit fields
|
||||
max_size_of_parameters = (BitsPerLong-1 -
|
||||
result_feature_size - parameter_feature_size -
|
||||
static_feature_size) / parameter_feature_size
|
||||
// Parameters take up full wordsize, minus the result and static bit fields.
|
||||
// Since fp_parameters_done is zero, termination field arises from shifting
|
||||
// in zero bits, and therefore occupies no extra space.
|
||||
// The sentinel value is all-zero-bits, which is impossible for a true
|
||||
// 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
|
||||
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
|
||||
void iterate_parameters(); // iterates over parameters only
|
||||
void iterate_parameters( uint64_t fingerprint );
|
||||
void iterate_returntype(); // iterates over returntype only
|
||||
void iterate(); // iterates over whole signature
|
||||
// Returns the word index of the current parameter;
|
||||
int parameter_index() const { return _parameter_index; }
|
||||
bool is_return_type() const { return parameter_index() < 0; }
|
||||
BasicType get_ret_type() const { return _return_type; }
|
||||
// Hey look: There are no virtual methods in this class.
|
||||
// So how is it customized? By calling do_parameters_on
|
||||
// an object which answers to "do_type(BasicType)".
|
||||
// By convention, this object is in the subclass
|
||||
// itself, so the call is "do_parameters_on(this)".
|
||||
// The effect of this is to inline the parsing loop
|
||||
// everywhere "do_parameters_on" is called.
|
||||
// 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
|
||||
virtual void do_bool () = 0;
|
||||
virtual void do_char () = 0;
|
||||
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 bool fp_is_static(fingerprint_t fingerprint) {
|
||||
assert(fp_is_valid(fingerprint), "invalid fingerprint");
|
||||
return fingerprint & fp_is_static_bit;
|
||||
}
|
||||
static BasicType return_type(uint64_t fingerprint) {
|
||||
assert(fingerprint != (uint64_t)CONST64(-1), "invalid fingerprint");
|
||||
return (BasicType) ((fingerprint >> static_feature_size) & result_feature_mask);
|
||||
static BasicType fp_return_type(fingerprint_t fingerprint) {
|
||||
assert(fp_is_valid(fingerprint), "invalid fingerprint");
|
||||
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:
|
||||
virtual void type_name(const char* name) = 0;
|
||||
|
||||
void do_bool() { type_name("jboolean"); }
|
||||
void do_char() { type_name("jchar" ); }
|
||||
void do_float() { type_name("jfloat" ); }
|
||||
void do_double() { type_name("jdouble" ); }
|
||||
void do_byte() { type_name("jbyte" ); }
|
||||
void do_short() { type_name("jshort" ); }
|
||||
void do_int() { type_name("jint" ); }
|
||||
void do_long() { type_name("jlong" ); }
|
||||
void do_void() { type_name("void" ); }
|
||||
void do_object(int begin, int end) { type_name("jobject" ); }
|
||||
void do_array (int begin, int end) { type_name("jobject" ); }
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
switch (type) {
|
||||
case T_BOOLEAN: type_name("jboolean"); break;
|
||||
case T_CHAR: type_name("jchar" ); break;
|
||||
case T_FLOAT: type_name("jfloat" ); break;
|
||||
case T_DOUBLE: type_name("jdouble" ); break;
|
||||
case T_BYTE: type_name("jbyte" ); break;
|
||||
case T_SHORT: type_name("jshort" ); break;
|
||||
case T_INT: type_name("jint" ); break;
|
||||
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:
|
||||
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.
|
||||
|
||||
class ArgumentSizeComputer: public SignatureInfo {
|
||||
class ArgumentSizeComputer: public SignatureIterator {
|
||||
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:
|
||||
ArgumentSizeComputer(Symbol* signature) : SignatureInfo(signature) {}
|
||||
|
||||
int size() { lazy_iterate_parameters(); return _size; }
|
||||
ArgumentSizeComputer(Symbol* signature);
|
||||
int size() { return _size; }
|
||||
};
|
||||
|
||||
|
||||
class ArgumentCount: public SignatureInfo {
|
||||
class ArgumentCount: public SignatureIterator {
|
||||
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:
|
||||
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.
|
||||
|
||||
class ResultTypeFinder: public SignatureInfo {
|
||||
private:
|
||||
void set(int size, BasicType type) { _return_type = type; }
|
||||
class ResultTypeFinder: public SignatureIterator {
|
||||
public:
|
||||
BasicType type() { lazy_iterate_return(); return _return_type; }
|
||||
|
||||
ResultTypeFinder(Symbol* signature) : SignatureInfo(signature) {}
|
||||
BasicType type() { return return_type(); }
|
||||
ResultTypeFinder(Symbol* signature) : SignatureIterator(signature) { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -219,52 +332,41 @@ class ResultTypeFinder: public SignatureInfo {
|
|||
// is a bitvector characterizing the methods signature (incl. the receiver).
|
||||
class Fingerprinter: public SignatureIterator {
|
||||
private:
|
||||
uint64_t _fingerprint;
|
||||
fingerprint_t _accumulator;
|
||||
int _param_size;
|
||||
int _shift_count;
|
||||
methodHandle mh;
|
||||
const Method* _method;
|
||||
|
||||
public:
|
||||
|
||||
void do_bool() { _fingerprint |= (((uint64_t)bool_parm) << _shift_count); _shift_count += parameter_feature_size; }
|
||||
void do_char() { _fingerprint |= (((uint64_t)char_parm) << _shift_count); _shift_count += parameter_feature_size; }
|
||||
void do_byte() { _fingerprint |= (((uint64_t)byte_parm) << _shift_count); _shift_count += parameter_feature_size; }
|
||||
void do_short() { _fingerprint |= (((uint64_t)short_parm) << _shift_count); _shift_count += parameter_feature_size; }
|
||||
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;
|
||||
void initialize_accumulator() {
|
||||
_accumulator = 0;
|
||||
_shift_count = fp_result_feature_size + fp_static_feature_size;
|
||||
_param_size = 0;
|
||||
}
|
||||
|
||||
uint64_t fingerprint() {
|
||||
// See if we fingerprinted this method already
|
||||
if (mh->constMethod()->fingerprint() != CONST64(0)) {
|
||||
return mh->constMethod()->fingerprint();
|
||||
}
|
||||
// Out-of-line method does it all in constructor:
|
||||
void compute_fingerprint_and_return_type(bool static_flag = false);
|
||||
|
||||
if (mh->size_of_parameters() > max_size_of_parameters ) {
|
||||
_fingerprint = (uint64_t)CONST64(-1);
|
||||
mh->constMethod()->set_fingerprint(_fingerprint);
|
||||
return _fingerprint;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
public:
|
||||
int size_of_parameters() const { return _param_size; }
|
||||
// fingerprint() and return_type() are in super class
|
||||
|
||||
Fingerprinter(const methodHandle& method)
|
||||
: SignatureIterator(method->signature()),
|
||||
_method(method()) {
|
||||
compute_fingerprint_and_return_type();
|
||||
}
|
||||
Fingerprinter(Symbol* signature, bool is_static)
|
||||
: SignatureIterator(signature),
|
||||
_method(NULL) {
|
||||
compute_fingerprint_and_return_type(is_static);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -281,35 +383,46 @@ class NativeSignatureIterator: public SignatureIterator {
|
|||
int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static)
|
||||
int _jni_offset; // the current parameter offset, starting with 0
|
||||
|
||||
void do_bool () { pass_int(); _jni_offset++; _offset++; }
|
||||
void do_char () { pass_int(); _jni_offset++; _offset++; }
|
||||
void do_float () { pass_float(); _jni_offset++; _offset++; }
|
||||
#ifdef _LP64
|
||||
void do_double() { pass_double(); _jni_offset++; _offset += 2; }
|
||||
#else
|
||||
void do_double() { pass_double(); _jni_offset += 2; _offset += 2; }
|
||||
#endif
|
||||
void do_byte () { pass_int(); _jni_offset++; _offset++; }
|
||||
void do_short () { pass_int(); _jni_offset++; _offset++; }
|
||||
void do_int () { pass_int(); _jni_offset++; _offset++; }
|
||||
#ifdef _LP64
|
||||
void do_long () { pass_long(); _jni_offset++; _offset += 2; }
|
||||
#else
|
||||
void do_long () { pass_long(); _jni_offset += 2; _offset += 2; }
|
||||
#endif
|
||||
void do_void () { ShouldNotReachHere(); }
|
||||
void do_object(int begin, int end) { pass_object(); _jni_offset++; _offset++; }
|
||||
void do_array (int begin, int end) { pass_object(); _jni_offset++; _offset++; }
|
||||
friend class SignatureIterator; // so do_parameters_on can call do_type
|
||||
void do_type(BasicType type) {
|
||||
switch (type) {
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT:
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
pass_int(); _jni_offset++; _offset++;
|
||||
break;
|
||||
case T_FLOAT:
|
||||
pass_float(); _jni_offset++; _offset++;
|
||||
break;
|
||||
case T_DOUBLE: {
|
||||
int jni_offset = LP64_ONLY(1) NOT_LP64(2);
|
||||
pass_double(); _jni_offset += jni_offset; _offset += 2;
|
||||
break;
|
||||
}
|
||||
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:
|
||||
methodHandle method() const { return _method; }
|
||||
int offset() const { return _offset; }
|
||||
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(); }
|
||||
virtual void pass_int() = 0;
|
||||
virtual void pass_long() = 0;
|
||||
virtual void pass_object() = 0;
|
||||
virtual void pass_object() = 0; // objects, arrays, inlines
|
||||
virtual void pass_float() = 0;
|
||||
#ifdef _LP64
|
||||
virtual void pass_double() = 0;
|
||||
|
@ -327,7 +440,9 @@ class NativeSignatureIterator: public SignatureIterator {
|
|||
_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}
|
||||
//
|
||||
|
@ -335,87 +450,132 @@ class NativeSignatureIterator: public SignatureIterator {
|
|||
// 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 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());
|
||||
}
|
||||
|
||||
|
||||
// Optimized path if we have the bitvector form of signature
|
||||
void iterate( uint64_t fingerprint ) {
|
||||
|
||||
void iterate(fingerprint_t fingerprint) {
|
||||
set_fingerprint(fingerprint);
|
||||
if (!is_static()) {
|
||||
// handle receiver (not handled by iterate because not in signature)
|
||||
pass_object(); _jni_offset++; _offset++;
|
||||
}
|
||||
|
||||
SignatureIterator::iterate_parameters( fingerprint );
|
||||
do_parameters_on(this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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 {
|
||||
private:
|
||||
Symbol* _signature;
|
||||
const Symbol* _signature;
|
||||
int _begin;
|
||||
int _end;
|
||||
int _limit;
|
||||
int _array_prefix; // count of '[' before the array element descr
|
||||
BasicType _type;
|
||||
bool _at_return_type;
|
||||
Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups
|
||||
GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced
|
||||
public:
|
||||
bool at_return_type() const { return _at_return_type; }
|
||||
bool is_done() const;
|
||||
void next_non_primitive(int t);
|
||||
void next() {
|
||||
Symbol* sig = _signature;
|
||||
int len = sig->utf8_length();
|
||||
if (_end >= len) {
|
||||
_end = len + 1;
|
||||
return;
|
||||
}
|
||||
int _state;
|
||||
Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups
|
||||
GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced
|
||||
|
||||
_begin = _end;
|
||||
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++;
|
||||
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");
|
||||
}
|
||||
|
||||
SignatureStream(Symbol* signature, bool is_method = true);
|
||||
public:
|
||||
bool is_method_signature() const { return (_state & (int)_s_method) != 0; }
|
||||
bool at_return_type() const { return _state == (int)_s_method_return; }
|
||||
bool is_done() const { return _state < 0; }
|
||||
void next();
|
||||
|
||||
SignatureStream(const Symbol* signature, bool is_method = true);
|
||||
~SignatureStream();
|
||||
|
||||
bool is_object() const; // True if this argument is an object
|
||||
bool is_array() const; // True if this argument is an array
|
||||
BasicType type() const { return _type; }
|
||||
Symbol* as_symbol();
|
||||
enum FailureMode { ReturnNull, NCDFError };
|
||||
bool is_reference() const { return is_reference_type(_type); }
|
||||
bool is_array() const { return _type == T_ARRAY; }
|
||||
bool is_primitive() const { return is_java_primitive(_type); }
|
||||
BasicType type() const { return _type; }
|
||||
|
||||
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);
|
||||
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();
|
||||
};
|
||||
|
||||
#ifdef ASSERT
|
||||
class SignatureVerifier : public StackObj {
|
||||
// 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
|
||||
class SignatureVerifier : public StackObj {
|
||||
public:
|
||||
static bool is_valid_method_signature(Symbol* sig);
|
||||
static bool is_valid_type_signature(Symbol* sig);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "precompiled.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// Basic error support
|
||||
|
@ -51,6 +52,20 @@ uint64_t OopEncodingHeapMax = 0;
|
|||
|
||||
// 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() {
|
||||
#ifdef ASSERT
|
||||
#ifdef _LP64
|
||||
|
@ -84,10 +99,13 @@ void basic_types_init() {
|
|||
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(signature_constants_sane(), "");
|
||||
|
||||
int num_type_chars = 0;
|
||||
for (int i = 0; i < 99; i++) {
|
||||
if (type2char((BasicType)i) != 0) {
|
||||
assert(char2type(type2char((BasicType)i)) == i, "proper inverses");
|
||||
assert(Signature::basic_type(type2char((BasicType)i)) == i, "proper inverses");
|
||||
num_type_chars++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -625,6 +625,24 @@ enum BasicType {
|
|||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
|
@ -693,6 +693,13 @@ enum BasicTypeSize {
|
|||
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:
|
||||
// all sub-word integral types are widened to T_INT
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue