OpenJDK / valhalla / valhalla
changeset 49040:ffeb876ac3cb lworld
Remove MVT verifier changes and prototype LWorld verifier changes
Reviewed-by: acorn, fparain, lfoltan
Contributed-by: harold.seigel@oracle.com
author | lfoltan |
---|---|
date | Thu, 01 Mar 2018 15:54:53 -0500 |
parents | ece7d51734ba |
children | 75ebb75d0d60 |
files | src/hotspot/share/classfile/verificationType.cpp src/hotspot/share/classfile/verifier.cpp src/hotspot/share/classfile/verifier.hpp test/hotspot/jtreg/runtime/valhalla/valuetypes/verifier/VloadTest.java test/hotspot/jtreg/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java |
diffstat | 5 files changed, 55 insertions(+), 479 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/share/classfile/verificationType.cpp Tue Feb 27 13:06:06 2018 -0800 +++ b/src/hotspot/share/classfile/verificationType.cpp Thu Mar 01 15:54:53 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ Verifier::trace_class_resolution(this_class, klass); } + if (this_class->access_flags().is_value_type()) return false; if (this_class->is_interface() && (!from_field_is_protected || from_name != vmSymbols::java_lang_Object())) { // If we are not trying to access a protected field or method in @@ -159,7 +160,6 @@ case Double_2nd: st->print("double_2nd"); break; case Null: st->print("null"); break; case ReferenceQuery: st->print("reference type"); break; - case ValueTypeQuery: st->print("value type"); break; case Category1Query: st->print("category1 type"); break; case Category2Query: st->print("category2 type"); break; case Category2_2ndQuery: st->print("category2_2nd type"); break;
--- a/src/hotspot/share/classfile/verifier.cpp Tue Feb 27 13:06:06 2018 -0800 +++ b/src/hotspot/share/classfile/verifier.cpp Thu Mar 01 15:54:53 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -55,6 +55,7 @@ #define NOFAILOVER_MAJOR_VERSION 51 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION 51 #define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION 52 +#define VALUETYPE_MAJOR_VERSION 55 #define MAX_ARRAY_DIMENSIONS 255 // Access to external entry for VerifyClassCodes - old byte code verifier @@ -239,7 +240,7 @@ return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class // or defineClass specified not to verify by default (flags override passed arg) - // We need to skip the following few for bootstrapping + // We need to skip the following four for bootstrapping name != vmSymbols::java_lang_Object() && name != vmSymbols::java_lang_Class() && name != vmSymbols::java_lang_String() && @@ -251,11 +252,6 @@ // Shared classes shouldn't have stackmaps either. !klass->is_shared() && - // A MVT derived value type contains no code atrribute - no private static - // methods, no instance methods, no <clinit>, no <init>. So while format - // checking is performed on it, verification is not. - (!((EnableMVT || EnableValhalla) && klass->access_flags().is_value_type())) && - // As of the fix for 4486457 we disable verification for all of the // dynamically-generated bytecodes associated with the 1.4 // reflection implementation, not just those associated with @@ -595,12 +591,6 @@ return TypeOrigin::implicit(vt); } -TypeOrigin ClassVerifier::valuetype_ctx(const char* sig, TRAPS) { - VerificationType vt = VerificationType::valuetype_type( - create_temporary_symbol(sig, (int)strlen(sig), THREAD)); - return TypeOrigin::implicit(vt); -} - void ClassVerifier::verify_class(TRAPS) { log_info(verification)("Verifying class %s with new format", _klass->external_name()); @@ -645,12 +635,6 @@ return; } - // Verify value type bytecodes if enabled and class file version supports them. - // Commented check out for now until class file version 54.1 is generated. - bool vbytecodes_allowed = (EnableMVT || EnableValhalla); - //_klass->major_version() >= Verifier::VALUETYPE_MAJOR_VERSION && - //_klass->minor_version() >= Verifier::VALUETYPE_MINOR_VERSION); - // Initial stack map frame: offset is 0, stack is initially empty. StackMapFrame current_frame(max_locals, max_stack, this); // Set initial locals @@ -990,37 +974,6 @@ } no_control_flow = false; break; } -// case Bytecodes::_vaload : { -// if (!vbytecodes_allowed) { -// class_format_error( -// "vaload not supported by this class file version (%d.%d), class %s", -// _klass->major_version(), _klass->minor_version(), _klass->external_name()); -// return; -// } -// type = current_frame.pop_stack( -// VerificationType::integer_type(), CHECK_VERIFY(this)); -// atype = current_frame.pop_stack( -// VerificationType::reference_check(), CHECK_VERIFY(this)); -// // The null check is strictly not be necessary, left in for future proofing. -// // Will be reconsidered if type indexes are removed. -// if (atype.is_null() || !atype.is_value_array()) { -// verify_error(ErrorContext::bad_type(bci, -// current_frame.stack_top_ctx(), -// TypeOrigin::implicit(VerificationType::reference_check())), -// bad_type_msg, "vaload"); -// return; -// } -// VerificationType component = atype.get_component(this, CHECK_VERIFY(this)); -// if (!component.is_valuetype()) { -// verify_error(ErrorContext::bad_type(bci, -// current_frame.stack_top_ctx(), -// TypeOrigin::implicit(VerificationType::valuetype_check())), -// bad_type_msg, "vaload"); -// return; -// } -// current_frame.push_stack(component, CHECK_VERIFY(this)); -// no_control_flow = false; break; -// } case Bytecodes::_istore : verify_istore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this)); no_control_flow = false; break; @@ -1187,28 +1140,6 @@ } // 4938384: relaxed constraint in JVMS 3nd edition. no_control_flow = false; break; -// case Bytecodes::_vastore : -// if (!vbytecodes_allowed) { -// class_format_error( -// "vastore not supported by this class file version (%d.%d), class %s", -// _klass->major_version(), _klass->minor_version(), _klass->external_name()); -// return; -// } -// type = current_frame.pop_stack(__value_type(), CHECK_VERIFY(this)); -// type2 = current_frame.pop_stack( -// VerificationType::integer_type(), CHECK_VERIFY(this)); -// atype = current_frame.pop_stack( -// VerificationType::reference_check(), CHECK_VERIFY(this)); -// // The null check is strictly not be necessary, left in for future proofing. -// // Will be reconsidered if type indexes are removed. -// if (atype.is_null() || !atype.is_value_array()) { -// verify_error(ErrorContext::bad_type(bci, -// current_frame.stack_top_ctx(), -// TypeOrigin::implicit(VerificationType::reference_check())), -// bad_type_msg, "vastore"); -// return; -// } -// no_control_flow = false; break; case Bytecodes::_pop : current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); @@ -1660,18 +1591,6 @@ verify_return_value(return_type, type, bci, ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; -// case Bytecodes::_vreturn : -// if (!vbytecodes_allowed) { -// class_format_error( -// "vreturn not supported by this class file version (%d.%d), class %s", -// _klass->major_version(), _klass->minor_version(), _klass->external_name()); -// return; -// } -// type = current_frame.pop_stack( -// VerificationType::valuetype_check(), CHECK_VERIFY(this)); -// verify_return_value(return_type, type, bci, -// ¤t_frame, CHECK_VERIFY(this)); -// no_control_flow = true; break; case Bytecodes::_return : if (return_type != VerificationType::bogus_type()) { verify_error(ErrorContext::bad_code(bci), @@ -1701,13 +1620,15 @@ &bcs, ¤t_frame, cp, false, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_withfield : - if (!vbytecodes_allowed) { + if (_klass->major_version() < VALUETYPE_MAJOR_VERSION) { class_format_error( - "vwithfield not supported by this class file version (%d.%d), class %s", + "withfield not supported by this class file version (%d.%d), class %s", _klass->major_version(), _klass->minor_version(), _klass->external_name()); return; } - verify_vwithfield(&bcs, ¤t_frame, cp, CHECK_VERIFY(this)); + // pass FALSE, operand can't be an array type for withfield. + verify_field_instructions( + &bcs, ¤t_frame, cp, false, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_invokevirtual : case Bytecodes::_invokespecial : @@ -1727,7 +1648,7 @@ index = bcs.get_index_u2(); verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); VerificationType new_class_type = - cp_index_to_reference_type(index, cp, CHECK_VERIFY(this)); + cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_class_type.is_object()) { verify_error(ErrorContext::bad_type(bci, TypeOrigin::cp(index, new_class_type)), @@ -1740,23 +1661,22 @@ } case Bytecodes::_defaultvalue : { - if (!vbytecodes_allowed) { + if (_klass->major_version() < VALUETYPE_MAJOR_VERSION) { class_format_error( - "vdefault not supported by this class file version (%d.%d), class %s", + "defaultvalue not supported by this class file version (%d.%d), class %s", _klass->major_version(), _klass->minor_version(), _klass->external_name()); return; } index = bcs.get_index_u2(); - verify_cp_value_type(bci, index, cp, CHECK_VERIFY(this)); - VerificationType new_value_type = - cp_index_to_valuetype(index, cp, CHECK_VERIFY(this)); - if (!new_value_type.is_valuetype()) { + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); + VerificationType vtype = cp_index_to_type(index, cp, CHECK_VERIFY(this)); + if (!vtype.is_object()) { verify_error(ErrorContext::bad_type(bci, - TypeOrigin::cp(index, new_value_type)), - "Illegal vdefault instruction"); + TypeOrigin::cp(index, vtype)), + "Illegal defaultvalue instruction"); return; } - current_frame.push_stack(new_value_type, CHECK_VERIFY(this)); + current_frame.push_stack(vtype, CHECK_VERIFY(this)); no_control_flow = false; break; } case Bytecodes::_newarray : @@ -1785,7 +1705,7 @@ index = bcs.get_index_u2(); verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); - VerificationType klass_type = cp_index_to_reference_type( + VerificationType klass_type = cp_index_to_type( index, cp, CHECK_VERIFY(this)); current_frame.push_stack(klass_type, CHECK_VERIFY(this)); no_control_flow = false; break; @@ -1807,9 +1727,9 @@ { index = bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3); - verify_cp_class_or_value_type(bci, index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); VerificationType new_array_type = - cp_index_to_reference_type(index, cp, CHECK_VERIFY(this)); + cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_array_type.is_array()) { verify_error(ErrorContext::bad_type(bci, TypeOrigin::cp(index, new_array_type)), @@ -1916,7 +1836,7 @@ } int catch_type_index = exhandlers.catch_type_index(i); if (catch_type_index != 0) { - VerificationType catch_type = cp_index_to_reference_type( + VerificationType catch_type = cp_index_to_type( catch_type_index, cp, CHECK_VERIFY(this)); VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); @@ -2019,7 +1939,7 @@ if (catch_type_index != 0) { if (was_recursively_verified()) return; // We know that this index refers to a subclass of Throwable - VerificationType catch_type = cp_index_to_reference_type( + VerificationType catch_type = cp_index_to_type( catch_type_index, cp, CHECK_VERIFY(this)); new_frame->push_stack(catch_type, CHECK_VERIFY(this)); } else { @@ -2062,10 +1982,6 @@ verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); unsigned int tag = cp->tag_at(index).value(); - if (tag == JVM_CONSTANT_Value) { - tag = SAFE_JVM_CONSTANT_Value; //avoid overflow - } - if ((types & (1 << tag)) == 0) { verify_error(ErrorContext::bad_cp_index(bci, index), "Illegal type at constant pool entry %d in class %s", @@ -2086,32 +2002,6 @@ } } -void ClassVerifier::verify_cp_value_type( - u2 bci, int index, const constantPoolHandle& cp, TRAPS) { - verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); - constantTag tag = cp->tag_at(index); - if (!tag.is_value_type() && !tag.is_unresolved_value_type()) { - verify_error(ErrorContext::bad_cp_index(bci, index), - "Illegal type at constant pool entry %d in class %s", - index, cp->pool_holder()->external_name()); - return; - } -} - -// Used for MVT value type overloaded bytecodes (anewarray, getfield, multianewarray) -void ClassVerifier::verify_cp_class_or_value_type( - u2 bci, int index, const constantPoolHandle& cp, TRAPS) { - verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); - constantTag tag = cp->tag_at(index); - if (!tag.is_klass() && !tag.is_unresolved_klass() && - !tag.is_value_type() && !tag.is_unresolved_value_type()) { - verify_error(ErrorContext::bad_cp_index(bci, index), - "Illegal type at constant pool entry %d in class %s", - index, cp->pool_holder()->external_name()); - return; - } -} - void ClassVerifier::verify_error(ErrorContext ctx, const char* msg, ...) { stringStream ss; @@ -2199,18 +2089,13 @@ constantTag tag = cp->tag_at(index); unsigned int types = 0; if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) { - if (!tag.is_unresolved_klass() && !tag.is_unresolved_value_type()) { + if (!tag.is_unresolved_klass()) { types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float) | (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class) - | (1 << SAFE_JVM_CONSTANT_Value) | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType) | (1 << JVM_CONSTANT_Dynamic); // Note: The class file parser already verified the legality of // MethodHandle and MethodType constants. - // Note: SAFE_JVM_CONSTANT_Value is used instead of JVM_CONSTANT_Value - // since JVM_CONSTANT_Value is an internally defined CP tag that is - // defined with a large value. When shifting left JVM_CONSTANT_Value - // would overrun the width of types. verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this)); } } else { @@ -2225,8 +2110,7 @@ current_frame->push_stack( VerificationType::reference_type( vmSymbols::java_lang_String()), CHECK_VERIFY(this)); - } else if (tag.is_klass() || tag.is_unresolved_klass() || - tag.is_value_type() || tag.is_unresolved_value_type()) { + } else if (tag.is_klass() || tag.is_unresolved_klass()) { current_frame->push_stack( VerificationType::reference_type( vmSymbols::java_lang_Class()), CHECK_VERIFY(this)); @@ -2386,32 +2270,16 @@ return; } - // Get referenced class or value type - constantTag field_class_tag = cp->tag_at(cp->klass_ref_index_at(index)); - VerificationType ref_class_type; - - // getfield is overloaded to allow for either a reference or value type - if (bcs->raw_code() == Bytecodes::_getfield && - (EnableMVT || EnableValhalla) && - (field_class_tag.is_value_type() || field_class_tag.is_unresolved_value_type())) { - ref_class_type = cp_value_index_to_type(index, cp, CHECK_VERIFY(this)); - if (!ref_class_type.is_valuetype()) { - verify_error(ErrorContext::bad_type(bcs->bci(), - TypeOrigin::cp(index, ref_class_type)), - "Expecting reference to value type in class %s at constant pool index %d", - _klass->external_name(), index); - return; - } - } else { - ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this)); - if (!ref_class_type.is_object() && - (!allow_arrays || !ref_class_type.is_array())) { - verify_error(ErrorContext::bad_type(bcs->bci(), - TypeOrigin::cp(index, ref_class_type)), - "Expecting reference to class in class %s at constant pool index %d", - _klass->external_name(), index); - return; - } + // Get referenced class type + VerificationType ref_class_type = cp_ref_index_to_type( + index, cp, CHECK_VERIFY(this)); + if (!ref_class_type.is_object() && + (!allow_arrays || !ref_class_type.is_array())) { + verify_error(ErrorContext::bad_type(bcs->bci(), + TypeOrigin::cp(index, ref_class_type)), + "Expecting reference to class in class %s at constant pool index %d", + _klass->external_name(), index); + return; } VerificationType target_class_type = ref_class_type; @@ -2444,6 +2312,13 @@ } break; } + case Bytecodes::_withfield: { + for (int i = n - 1; i >= 0; i--) { + current_frame->pop_stack(field_type[i], CHECK_VERIFY(this)); + } + current_frame->push_stack(target_class_type, CHECK_VERIFY(this)); + break; + } case Bytecodes::_getfield: { stack_object_type = current_frame->pop_stack( target_class_type, CHECK_VERIFY(this)); @@ -2510,74 +2385,6 @@ } } -void ClassVerifier::verify_vwithfield(RawBytecodeStream* bcs, - StackMapFrame* current_frame, - const constantPoolHandle& cp, - TRAPS) { - u2 index = bcs->get_index_u2(); - verify_cp_type(bcs->bci(), index, cp, - 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); - - // Get field name and signature - Symbol* field_name = cp->name_ref_at(index); - Symbol* field_sig = cp->signature_ref_at(index); - - if (!SignatureVerifier::is_valid_type_signature(field_sig)) { - class_format_error( - "Invalid signature for field in value type %s referenced " - "from constant pool index %d", _klass->external_name(), index); - return; - } - - // Check referenced value type - VerificationType ref_value_type = cp_value_index_to_type( - index, cp, CHECK_VERIFY(this)); - if (!ref_value_type.is_valuetype()) { - verify_error(ErrorContext::bad_type(bcs->bci(), - TypeOrigin::cp(index, ref_value_type)), - "Expecting reference to value type in class %s at constant pool index %d", - _klass->external_name(), index); - return; - } - VerificationType target_value_type = ref_value_type; - - assert(sizeof(VerificationType) == sizeof(uintptr_t), - "buffer type must match VerificationType size"); - uintptr_t field_type_buffer[2]; - VerificationType* field_type = (VerificationType*)field_type_buffer; - // If we make a VerificationType[2] array directly, the compiler calls - // to the c-runtime library to do the allocation instead of just - // stack allocating it. Plus it would run constructors. This shows up - // in performance profiles. - - SignatureStream sig_stream(field_sig, false); - int n = change_sig_to_verificationType( - &sig_stream, field_type, CHECK_VERIFY(this)); - u2 bci = bcs->bci(); - - // The type of value2 must be compatible with the descriptor of the referenced field. - // n could be 2 if it is a double or long. - for (int i = n - 1; i >= 0; i--) { - current_frame->pop_stack(field_type[i], CHECK_VERIFY(this)); - } - - // The type of value1 must be the direct value class type appearing in the field reference. - VerificationType stack_object_type = current_frame->pop_stack(CHECK_VERIFY(this)); - - bool is_assignable = target_value_type.is_assignable_from( - stack_object_type, this, false, CHECK_VERIFY(this)); - if (!is_assignable) { - verify_error(ErrorContext::bad_type(bci, - current_frame->stack_top_ctx(), - TypeOrigin::cp(index, target_value_type)), - "Bad type on operand stack in vwithfield"); - return; - } - - // The derived value class instance from another, modifying a field - current_frame->push_stack(stack_object_type, CHECK_VERIFY(this)); -} - // Look at the method's handlers. If the bci is in the handler's try block // then check if the handler_pc is already on the stack. If not, push it // unless the handler has already been scanned. @@ -2847,7 +2654,7 @@ verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this)); // The method must be an <init> method of the indicated class - VerificationType new_class_type = cp_index_to_reference_type( + VerificationType new_class_type = cp_index_to_type( new_class_index, cp, CHECK_VERIFY(this)); if (!new_class_type.equals(ref_class_type)) { verify_error(ErrorContext::bad_type(bci, @@ -2955,7 +2762,7 @@ return; } - // Get referenced class or value type + // Get referenced class VerificationType ref_class_type; if (opcode == Bytecodes::_invokedynamic) { if (_klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { @@ -2965,14 +2772,7 @@ return; } } else { - constantTag method_class_tag = cp->tag_at(cp->klass_ref_index_at(index)); - if (EnableValhalla && - opcode == Bytecodes::_invokevirtual && - (method_class_tag.is_value_type() || method_class_tag.is_unresolved_value_type())) { - ref_class_type = cp_value_index_to_type(index, cp, CHECK_VERIFY(this)); - } else { - ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this)); - } + ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this)); } // For a small signature length, we just allocate 128 bytes instead @@ -3197,18 +2997,13 @@ void ClassVerifier::verify_anewarray( u2 bci, u2 index, const constantPoolHandle& cp, StackMapFrame* current_frame, TRAPS) { - verify_cp_class_or_value_type(bci, index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame->pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); if (was_recursively_verified()) return; - constantTag class_tag = cp->tag_at(index); - VerificationType component_type; - if (class_tag.is_value_type() || class_tag.is_unresolved_value_type()) { - component_type = cp_index_to_valuetype(index, cp, CHECK_VERIFY(this)); - } else { - component_type = cp_index_to_reference_type(index, cp, CHECK_VERIFY(this)); - } + VerificationType component_type = + cp_index_to_type(index, cp, CHECK_VERIFY(this)); int length; char* arr_sig_str; if (component_type.is_array()) { // it's an array @@ -3227,11 +3022,11 @@ strncpy(&arr_sig_str[1], component_name, length - 1); } else { // it's an object or interface const char* component_name = component_type.name()->as_utf8(); - // add one dimension to component with 'L' or 'Q' (value type) prepended and ';' appended. + // add one dimension to component with 'L' prepended and ';' appended. length = (int)strlen(component_name) + 3; arr_sig_str = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, length); arr_sig_str[0] = '['; - arr_sig_str[1] = component_type.is_reference() ? 'L' : 'Q'; + arr_sig_str[1] = 'L'; strncpy(&arr_sig_str[2], component_name, length - 2); arr_sig_str[length - 1] = ';'; }
--- a/src/hotspot/share/classfile/verifier.hpp Tue Feb 27 13:06:06 2018 -0800 +++ b/src/hotspot/share/classfile/verifier.hpp Thu Mar 01 15:54:53 2018 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -33,10 +33,6 @@ #include "utilities/exceptions.hpp" #include "utilities/growableArray.hpp" -// For bit tests involving JVM_CONSTANT_Value during verification, -// define a "safe" number to avoid integer overflow of types -#define SAFE_JVM_CONSTANT_Value JVM_CONSTANT_ExternalMax - // The verifier class class Verifier : AllStatic { public: @@ -46,8 +42,6 @@ INVOKEDYNAMIC_MAJOR_VERSION = 51, NO_RELAX_ACCESS_CTRL_CHECK_VERSION = 52, DYNAMICCONSTANT_MAJOR_VERSION = 55, - VALUETYPE_MAJOR_VERSION = 53, - VALUETYPE_MINOR_VERSION = 1 }; typedef enum { ThrowException, NoException } Mode; @@ -278,12 +272,7 @@ VerificationType cp_ref_index_to_type( int index, const constantPoolHandle& cp, TRAPS) { - return cp_index_to_reference_type(cp->klass_ref_index_at(index), cp, THREAD); - } - - VerificationType cp_value_index_to_type( - int index, const constantPoolHandle& cp, TRAPS) { - return cp_index_to_valuetype(cp->klass_ref_index_at(index), cp, THREAD); + return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD); } bool is_protected_access( @@ -294,8 +283,6 @@ void verify_cp_type(u2 bci, int index, const constantPoolHandle& cp, unsigned int types, TRAPS); void verify_cp_class_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS); - void verify_cp_value_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS); - void verify_cp_class_or_value_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS); u2 verify_stackmap_table( u2 stackmap_index, u2 bci, StackMapFrame* current_frame, @@ -317,10 +304,6 @@ RawBytecodeStream* bcs, StackMapFrame* current_frame, const constantPoolHandle& cp, bool allow_arrays, TRAPS); - void verify_vwithfield( - RawBytecodeStream* bcs, StackMapFrame* current_frame, - const constantPoolHandle& cp, TRAPS); - void verify_invoke_init( RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool in_try_block, @@ -365,7 +348,6 @@ bool name_in_supers(Symbol* ref_name, InstanceKlass* current); VerificationType object_type() const; - VerificationType __value_type() const; InstanceKlass* _klass; // the class being verified methodHandle _method; // current method being verified @@ -426,14 +408,10 @@ int change_sig_to_verificationType( SignatureStream* sig_type, VerificationType* inference_type, TRAPS); - VerificationType cp_index_to_reference_type(int index, const constantPoolHandle& cp, TRAPS) { + VerificationType cp_index_to_type(int index, const constantPoolHandle& cp, TRAPS) { return VerificationType::reference_type(cp->klass_name_at(index)); } - VerificationType cp_index_to_valuetype(int index, const constantPoolHandle& cp, TRAPS) { - return VerificationType::valuetype_type(cp->klass_name_at(index)); - } - // Keep a list of temporary symbols created during verification because // their reference counts need to be decremented when the verifier object // goes out of scope. Since these symbols escape the scope in which they're @@ -450,7 +428,6 @@ } TypeOrigin ref_ctx(const char* str, TRAPS); - TypeOrigin valuetype_ctx(const char* str, TRAPS); }; @@ -460,14 +437,12 @@ switch (bt) { case T_OBJECT: case T_ARRAY: - case T_VALUETYPE: { Symbol* name = sig_type->as_symbol(CHECK_0); // Create another symbol to save as signature stream unreferences this symbol. Symbol* name_copy = create_temporary_symbol(name); assert(name_copy == name, "symbols don't match"); - *inference_type = ((bt == T_VALUETYPE) ? VerificationType::valuetype_type(name_copy) : - VerificationType::reference_type(name_copy)); + *inference_type = VerificationType::reference_type(name_copy); return 1; } case T_LONG:
--- a/test/hotspot/jtreg/runtime/valhalla/valuetypes/verifier/VloadTest.java Tue Feb 27 13:06:06 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2017, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package runtime.valhalla.valuetypes.verifier; - -import java.lang.invoke.*; - -import jdk.experimental.value.MethodHandleBuilder; -import sun.hotspot.WhiteBox; - -/** - * @test VloadTest - * @summary Test vload opcode - * @modules java.base/jdk.experimental.value - * jdk.incubator.mvt - * @library /test/lib - * @compile -XDenableValueTypes VloadTest.java - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xint -XX:+UseG1GC -Xmx128m -XX:+EnableMVT - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * runtime.valhalla.valuetypes.verifier.VloadTest - */ -public class VloadTest { - - public static void main(String[] args) throws Throwable{ - testBytecodes(); - } - - // Test that vload cannot load an integer. - public static void testBytecodes() throws Throwable { - try { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - - Object array = MethodHandleBuilder.loadCode( - lookup, - "vloadAnInteger", - MethodType.methodType(Object.class, Integer.TYPE), - CODE->{ - CODE - .vload(0) // Attempt to vload an Integer - .aconst_null() - .areturn(); - }).invoke(1000); - } catch (Throwable t) { - if (!t.getMessage().contains("java.lang.VerifyError: Bad local variable type")) { - throw t; - } else { - System.out.println("Successful detection of vload verification error"); - } - } - } -}
--- a/test/hotspot/jtreg/runtime/valhalla/valuetypes/verifier/VunboxErrorIndex.java Tue Feb 27 13:06:06 2018 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2017, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package runtime.valhalla.valuetypes.verifier; - -import java.lang.invoke.*; -import jdk.incubator.mvt.ValueType; -import jdk.experimental.value.MethodHandleBuilder; - -import static jdk.test.lib.Asserts.*; - -/* - * @test VunboxErrorIndex - * @summary Exercise the verifier for vunbox bytecode with a non-value type CP index. - * @modules java.base/jdk.experimental.value - * jdk.incubator.mvt - * @library /test/lib - * @build runtime.valhalla.valuetypes.verifier.ValueCapableClass - * @run main/othervm -Xint -verify -XX:+EnableMVT runtime.valhalla.valuetypes.verifier.VunboxErrorIndex - */ -public class VunboxErrorIndex { - - public static void main(String[] args) { - testCorrectBoxing(); - testIncorrectBoxing(); - } - - public static void testCorrectBoxing() { - Class<?> vcc = ValueCapableClass.class; - Class<?> dvt = ValueType.forClass(vcc).valueClass(); - - MethodHandle newDvt = newDvtMh(dvt); - MethodHandle box = boxMh(dvt, vcc); - MethodHandle unbox = unboxMh(vcc, dvt); - - ValueCapableClass newObject = ValueCapableClass.create(3, (short)7, (short)11); - ValueCapableClass newBoxed = null; - - try { - ValueCapableClass boxed = (ValueCapableClass) MethodHandles.filterReturnValue(newDvt, box).invokeExact(); - // Assuming MVT1.0, where source has no way of holding an actual value at the language level, so: box(unbox(Object)) - newBoxed = (ValueCapableClass) MethodHandles.filterReturnValue(unbox, box).invokeExact(newObject); - } - catch (Throwable t) { fail("Invokation Exception", t); } - - assertTrue(newObject.getX() == newBoxed.getX()); - assertTrue(newObject.getY() == newBoxed.getY()); - assertTrue(newObject.getZ() == newBoxed.getZ()); - } - - public static void testIncorrectBoxing() { - Class<?> vcc = ValueCapableClass.class; - Class<?> dvt = ValueType.forClass(vcc).valueClass(); - - MethodHandle newDvt = newDvtMh(dvt); - MethodHandle box = boxMh(dvt, String.class); // Illegal box type - try { - MethodHandles.filterReturnValue(newDvt, box).invoke(); - fail("Expected ClassCastException"); - } - catch (ClassCastException cce) {} - catch (Throwable t) { fail("Invokation Exception", t); } - - // With -verify, this test will yield a VerifyError - // since the constant pool entry at the index is not a - // symbolic reference to a direct value class type. - try { - MethodHandle unbox = unboxMh(vcc, String.class); // Illegal unbox type - unbox.invoke(ValueCapableClass.create()); - fail("Expected VerifyError"); - } - catch (Throwable t) { - if (!t.getMessage().contains("java.lang.VerifyError")) { - fail("Invokation Exception", t); - } - } - } - - /* - Create new DVT via loading a value array element. Why this workaround: - 1) to avoid "ValueType.defaultValueConstant()" which may or may not be implemented with vunbox - */ - public static MethodHandle newDvtMh(Class<?> dvt) { - return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "newDvt", MethodType.methodType(dvt), CODE->{ - CODE.iconst_1().anewarray(dvt).iconst_0().vaload().vreturn(); - }); - } - - public static MethodHandle boxMh(Class<?> inClass, Class<?> outClass) { - return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "box", MethodType.methodType(outClass, inClass), CODE->{ - CODE.vload(0).vbox(outClass).areturn(); - }); - } - - public static MethodHandle unboxMh(Class<?> inClass, Class<?> outClass) { - return MethodHandleBuilder.loadCode(MethodHandles.lookup(), "box", MethodType.methodType(outClass, inClass), CODE->{ - CODE.aload(0).vunbox(outClass).vreturn(); - }); - } - -}