diff --git a/src/hotspot/share/classfile/bytecodeAssembler.cpp b/src/hotspot/share/classfile/bytecodeAssembler.cpp index 399f9ee65a9..3a8faf43804 100644 --- a/src/hotspot/share/classfile/bytecodeAssembler.cpp +++ b/src/hotspot/share/classfile/bytecodeAssembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, 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,15 +25,22 @@ #include "precompiled.hpp" #include "classfile/bytecodeAssembler.hpp" +#include "classfile/vmSymbols.hpp" #include "interpreter/bytecodes.hpp" #include "memory/oopFactory.hpp" #include "oops/constantPool.hpp" #include "runtime/handles.inline.hpp" #include "utilities/bytes.hpp" -u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) { +u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe, TRAPS) { - u2 index = _entries.length(); + // Check for overflow + int new_size = _orig->length() + _entries.length(); + if (new_size > USHRT_MAX) { + THROW_MSG_0(vmSymbols::java_lang_InternalError(), "default methods constant pool overflowed"); + } + + u2 index = checked_cast(_entries.length()); bool created = false; u2* probe = _indices.put_if_absent(bcpe, index, &created); if (created) { @@ -41,7 +48,7 @@ u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) { } else { index = *probe; } - return index + _orig->length(); + return checked_cast(index + _orig->length()); } ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const { @@ -49,9 +56,10 @@ ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const { return _orig; } + int new_size = _orig->length() + _entries.length(); ConstantPool* cp = ConstantPool::allocate( _orig->pool_holder()->class_loader_data(), - _orig->length() + _entries.length(), CHECK_NULL); + new_size, CHECK_NULL); cp->set_pool_holder(_orig->pool_holder()); constantPoolHandle cp_h(THREAD, cp); @@ -114,29 +122,20 @@ void BytecodeAssembler::append(u4 imm_u4) { Bytes::put_Java_u4(_code->adr_at(_code->length() - 4), imm_u4); } -void BytecodeAssembler::xload(u4 index, u1 onebyteop, u1 twobyteop) { - if (index < 4) { - _code->append(onebyteop + index); - } else { - _code->append(twobyteop); - _code->append((u2)index); - } -} - void BytecodeAssembler::dup() { _code->append(Bytecodes::_dup); } -void BytecodeAssembler::_new(Symbol* sym) { - u2 cpool_index = _cp->klass(sym); +void BytecodeAssembler::_new(Symbol* sym, TRAPS) { + u2 cpool_index = _cp->klass(sym, CHECK); _code->append(Bytecodes::_new); append(cpool_index); } -void BytecodeAssembler::load_string(Symbol* sym) { - u2 cpool_index = _cp->string(sym); +void BytecodeAssembler::load_string(Symbol* sym, TRAPS) { + u2 cpool_index = _cp->string(sym, CHECK); if (cpool_index < 0x100) { - ldc(cpool_index); + ldc((u1)cpool_index); } else { ldc_w(cpool_index); } @@ -156,111 +155,27 @@ void BytecodeAssembler::athrow() { _code->append(Bytecodes::_athrow); } -void BytecodeAssembler::iload(u4 index) { - xload(index, Bytecodes::_iload_0, Bytecodes::_iload); -} - -void BytecodeAssembler::lload(u4 index) { - xload(index, Bytecodes::_lload_0, Bytecodes::_lload); -} - -void BytecodeAssembler::fload(u4 index) { - xload(index, Bytecodes::_fload_0, Bytecodes::_fload); -} - -void BytecodeAssembler::dload(u4 index) { - xload(index, Bytecodes::_dload_0, Bytecodes::_dload); -} - -void BytecodeAssembler::aload(u4 index) { - xload(index, Bytecodes::_aload_0, Bytecodes::_aload); -} - -void BytecodeAssembler::load(BasicType bt, u4 index) { - switch (bt) { - case T_BOOLEAN: - case T_CHAR: - case T_BYTE: - case T_SHORT: - case T_INT: iload(index); break; - case T_FLOAT: fload(index); break; - case T_DOUBLE: dload(index); break; - case T_LONG: lload(index); break; - default: - if (is_reference_type(bt)) { - aload(index); - break; - } - ShouldNotReachHere(); - } -} - -void BytecodeAssembler::checkcast(Symbol* sym) { - u2 cpool_index = _cp->klass(sym); - _code->append(Bytecodes::_checkcast); - append(cpool_index); -} - -void BytecodeAssembler::invokespecial(Method* method) { - invokespecial(method->klass_name(), method->name(), method->signature()); -} - -void BytecodeAssembler::invokespecial(Symbol* klss, Symbol* name, Symbol* sig) { - u2 methodref_index = _cp->methodref(klss, name, sig); +void BytecodeAssembler::invokespecial(Symbol* klss, Symbol* name, Symbol* sig, TRAPS) { + u2 methodref_index = _cp->methodref(klss, name, sig, CHECK); _code->append(Bytecodes::_invokespecial); append(methodref_index); } -void BytecodeAssembler::invokevirtual(Method* method) { - invokevirtual(method->klass_name(), method->name(), method->signature()); -} +int BytecodeAssembler::assemble_method_error(BytecodeConstantPool* cp, + BytecodeBuffer* buffer, + Symbol* errorName, + Symbol* message, TRAPS) { -void BytecodeAssembler::invokevirtual(Symbol* klss, Symbol* name, Symbol* sig) { - u2 methodref_index = _cp->methodref(klss, name, sig); - _code->append(Bytecodes::_invokevirtual); - append(methodref_index); -} + Symbol* init = vmSymbols::object_initializer_name(); + Symbol* sig = vmSymbols::string_void_signature(); -void BytecodeAssembler::ireturn() { - _code->append(Bytecodes::_ireturn); -} + BytecodeAssembler assem(buffer, cp); -void BytecodeAssembler::lreturn() { - _code->append(Bytecodes::_lreturn); -} + assem._new(errorName, CHECK_0); + assem.dup(); + assem.load_string(message, CHECK_0); + assem.invokespecial(errorName, init, sig, CHECK_0); + assem.athrow(); -void BytecodeAssembler::freturn() { - _code->append(Bytecodes::_freturn); -} - -void BytecodeAssembler::dreturn() { - _code->append(Bytecodes::_dreturn); -} - -void BytecodeAssembler::areturn() { - _code->append(Bytecodes::_areturn); -} - -void BytecodeAssembler::_return() { - _code->append(Bytecodes::_return); -} - -void BytecodeAssembler::_return(BasicType bt) { - switch (bt) { - case T_BOOLEAN: - case T_CHAR: - case T_BYTE: - case T_SHORT: - case T_INT: ireturn(); break; - case T_FLOAT: freturn(); break; - case T_DOUBLE: dreturn(); break; - case T_LONG: lreturn(); break; - case T_VOID: _return(); break; - default: - if (is_reference_type(bt)) { - areturn(); - break; - } - ShouldNotReachHere(); - } + return 3; // max stack size: [ exception, exception, string ] } diff --git a/src/hotspot/share/classfile/bytecodeAssembler.hpp b/src/hotspot/share/classfile/bytecodeAssembler.hpp index 192e996df5f..4505db28aef 100644 --- a/src/hotspot/share/classfile/bytecodeAssembler.hpp +++ b/src/hotspot/share/classfile/bytecodeAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, 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,7 @@ class BytecodeConstantPool : ResourceObj { GrowableArray _entries; IndexHash _indices; - u2 find_or_add(BytecodeCPEntry const& bcpe); + u2 find_or_add(BytecodeCPEntry const& bcpe, TRAPS); public: @@ -144,25 +144,30 @@ class BytecodeConstantPool : ResourceObj { return _orig->pool_holder(); } - u2 utf8(Symbol* sym) { - return find_or_add(BytecodeCPEntry::utf8(sym)); + u2 utf8(Symbol* sym, TRAPS) { + return find_or_add(BytecodeCPEntry::utf8(sym), THREAD); } - u2 klass(Symbol* class_name) { - return find_or_add(BytecodeCPEntry::klass(utf8(class_name))); + u2 klass(Symbol* class_name, TRAPS) { + u2 utf8_entry = utf8(class_name, CHECK_0); + return find_or_add(BytecodeCPEntry::klass(utf8_entry), THREAD); } - u2 string(Symbol* str) { - return find_or_add(BytecodeCPEntry::string(utf8(str))); + u2 string(Symbol* str, TRAPS) { + u2 utf8_entry = utf8(str, CHECK_0); + return find_or_add(BytecodeCPEntry::string(utf8_entry), THREAD); } - u2 name_and_type(Symbol* name, Symbol* sig) { - return find_or_add(BytecodeCPEntry::name_and_type(utf8(name), utf8(sig))); + u2 name_and_type(Symbol* name, Symbol* sig, TRAPS) { + u2 utf8_name = utf8(name, CHECK_0); + u2 utf8_sig = utf8(sig, CHECK_0); + return find_or_add(BytecodeCPEntry::name_and_type(utf8_name, utf8_sig), THREAD); } - u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig) { - return find_or_add(BytecodeCPEntry::methodref( - klass(class_name), name_and_type(name, sig))); + u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig, TRAPS) { + u2 klass_entry = klass(class_name, CHECK_0); + u2 type_entry = name_and_type(name, sig, CHECK_0); + return find_or_add(BytecodeCPEntry::methodref(klass_entry, type_entry), THREAD); } ConstantPool* create_constant_pool(TRAPS) const; @@ -179,37 +184,22 @@ class BytecodeAssembler : StackObj { void append(u2 imm_u2); void append(u4 imm_u4); - void xload(u4 index, u1 quick, u1 twobyte); + void athrow(); + void dup(); + void invokespecial(Symbol* cls, Symbol* name, Symbol* sig, TRAPS); + void ldc(u1 index); + void ldc_w(u2 index); + void _new(Symbol* sym, TRAPS); + void load_string(Symbol* sym, TRAPS); public: BytecodeAssembler(BytecodeBuffer* buffer, BytecodeConstantPool* cp) : _code(buffer), _cp(cp) {} - void aload(u4 index); - void areturn(); - void athrow(); - void checkcast(Symbol* sym); - void dload(u4 index); - void dreturn(); - void dup(); - void fload(u4 index); - void freturn(); - void iload(u4 index); - void invokespecial(Method* method); - void invokespecial(Symbol* cls, Symbol* name, Symbol* sig); - void invokevirtual(Method* method); - void invokevirtual(Symbol* cls, Symbol* name, Symbol* sig); - void ireturn(); - void ldc(u1 index); - void ldc_w(u2 index); - void lload(u4 index); - void lreturn(); - void _new(Symbol* sym); - void _return(); - - void load_string(Symbol* sym); - void load(BasicType bt, u4 index); - void _return(BasicType bt); + static int assemble_method_error(BytecodeConstantPool* cp, + BytecodeBuffer* buffer, + Symbol* errorName, + Symbol* message, TRAPS); }; #endif // SHARE_CLASSFILE_BYTECODEASSEMBLER_HPP diff --git a/src/hotspot/share/classfile/defaultMethods.cpp b/src/hotspot/share/classfile/defaultMethods.cpp index 2ff277cda47..d02f89a2ccc 100644 --- a/src/hotspot/share/classfile/defaultMethods.cpp +++ b/src/hotspot/share/classfile/defaultMethods.cpp @@ -865,23 +865,6 @@ void DefaultMethods::generate_default_methods( log_debug(defaultmethods)("Default method processing complete"); } -static int assemble_method_error( - BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message) { - - Symbol* init = vmSymbols::object_initializer_name(); - Symbol* sig = vmSymbols::string_void_signature(); - - BytecodeAssembler assem(buffer, cp); - - assem._new(errorName); - assem.dup(); - assem.load_string(message); - assem.invokespecial(errorName, init, sig); - assem.athrow(); - - return 3; // max stack size: [ exception, exception, string ] -} - static Method* new_method( BytecodeConstantPool* cp, BytecodeBuffer* bytecodes, Symbol* name, Symbol* sig, AccessFlags flags, int max_stack, int params, @@ -901,8 +884,10 @@ static Method* new_method( mt, name, CHECK_NULL); m->set_constants(nullptr); // This will get filled in later - m->set_name_index(cp->utf8(name)); - m->set_signature_index(cp->utf8(sig)); + u2 name_index = cp->utf8(name, CHECK_NULL); + m->set_name_index(name_index); + u2 sig_index = cp->utf8(sig, CHECK_NULL); + m->set_signature_index(sig_index); m->constMethod()->compute_from_signature(sig, flags.is_static()); assert(m->size_of_parameters() == params, "should be computed above"); m->set_max_stack(max_stack); @@ -989,8 +974,8 @@ static void create_defaults_and_exceptions(GrowableArray* slot } else { buffer->clear(); } - int max_stack = assemble_method_error(&bpool, buffer, - method->get_exception_name(), method->get_exception_message()); + int max_stack = BytecodeAssembler::assemble_method_error(&bpool, buffer, + method->get_exception_name(), method->get_exception_message(), CHECK); AccessFlags flags = accessFlags_from( JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE); Method* m = new_method(&bpool, buffer, slot->name(), slot->signature(), @@ -1073,7 +1058,12 @@ static void merge_in_new_methods(InstanceKlass* klass, Array* original_ordering = klass->method_ordering(); Array* merged_ordering = Universe::the_empty_int_array(); - int new_size = klass->methods()->length() + new_methods->length(); + int new_methods_length = klass->methods()->length() + new_methods->length(); + if (new_methods_length > USHRT_MAX) { + THROW_MSG(vmSymbols::java_lang_InternalError(), + "error methods for default method processing created too many methods"); + } + u2 new_size = static_cast(new_methods_length); Array* merged_methods = MetadataFactory::new_array( klass->class_loader_data(), new_size, nullptr, CHECK); @@ -1091,7 +1081,7 @@ static void merge_in_new_methods(InstanceKlass* klass, int orig_idx = 0; int new_idx = 0; - for (int i = 0; i < new_size; ++i) { + for (u2 i = 0; i < new_size; ++i) { Method* orig_method = nullptr; Method* new_method = nullptr; if (orig_idx < original_methods->length()) {