On Fri, 30 Jun 2023 01:52:40 GMT, David Holmes <dhol...@openjdk.org> wrote:
>> Coleen Phillimore has updated the pull request incrementally with one >> additional commit since the last revision: >> >> Add a comment about u1 cast to new_index for the ldc bytecode. > > src/hotspot/share/oops/constMethod.hpp line 327: > >> 325: >> 326: // code size >> 327: u2 code_size() const { return _code_size; } > > The `code_length` of a `Code` attribute is `u4` - why is `u2` appropriate > here? The code_length attribute is defined in the class file specification as u4, but further specifies that: code_length The value of the code_length item gives the number of bytes in the code array for this method. The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536. So we store code_length as a u2 to save space in the ConstMethod. That's the size of the field _code_size. There are checks in set_code_size and in the ClassFileParser to verify this: guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE, "Invalid method Code length %u in class file %s", code_length, CHECK_NULL); And further when assigning code_size: void set_code_size(int size) { assert(max_method_code_size < (1 << 16), "u2 is too small to hold method code size in general"); assert(0 <= size && size <= max_method_code_size, "invalid code size"); _code_size = (u2)size; } At one point, there was discussion of expanding the code_size to u4. If that decision is made, we should change these types. I made the return type match the field type because it's copied when we create a new method. I did that to avoid a cast. > src/hotspot/share/oops/method.hpp line 257: > >> 255: >> 256: // code size >> 257: u2 code_size() const { return >> constMethod()->code_size(); } > > Again why is this not u4? see above. > src/hotspot/share/oops/method.hpp line 269: > >> 267: // return original max stack size for method verification >> 268: u2 verifier_max_stack() const { return >> constMethod()->max_stack(); } >> 269: int max_stack() const { return >> constMethod()->max_stack() + extra_stack_entries(); } > > So this has to be greater than a `u2` because of the extra entries? Yes. > src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp line 310: > >> 308: write_attribute_name_index("MethodParameters"); >> 309: write_u4(size); >> 310: write_u1((u1)length); > > What is the rule for using a plain cast versus a checked_cast? If the code above explicitly checks for the value of the int, then I don't use checked_cast<>. The explicit checks are more descriptive of the expectations and that assert would be better than the checked_cast<> assert which is somewhat generic. > src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp line 402: > >> 400: length += sizeof(u2); // bootstrap_method_ref >> 401: length += sizeof(u2); // num_bootstrap_arguments >> 402: length += (int)sizeof(u2) * num_bootstrap_arguments; // >> bootstrap_arguments[num_bootstrap_arguments] > > Not clear why the int cast is used given length is a u4? I could change that to u4. It's the same thing. It just can't be size_t. I really don't know why the C++ compiler gives this a Wconversion warning and not the lines above it. src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp:402:12: warning: conversion from 'long unsigned int' to 'u4' {aka 'unsigned int'} may change value [-Wconversion] 402 | length += sizeof(u2) * num_bootstrap_arguments; // bootstrap_arguments[num_bootstrap_arguments] | ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > src/hotspot/share/prims/jvmtiRawMonitor.cpp line 83: > >> 81: bool >> 82: JvmtiRawMonitor::is_valid() { >> 83: uint64_t value = 0; > > Why `uint64_t` here when `JvmtiEnvBase::is_valid` uses `jlong`? It's the same type. Since we're not already using a jlong in this function, I used the preferable uint64_t. I can make it jlong if you prefer that. > src/hotspot/share/prims/jvmtiRawMonitor.cpp line 385: > >> 383: OrderAccess::fence(); >> 384: >> 385: int save = _recursions; > > `_recursions` is `intx` JvmtiRawMonitor _recursions is an int. Maybe it shouldn't be. You could file an RFE to change that if it's wrong. volatile int _recursions; // recursion count, 0 for first entry > src/hotspot/share/prims/jvmtiTrace.cpp line 205: > >> 203: _trace_flags[i] |= bits; >> 204: } else { >> 205: _trace_flags[i] &= (jbyte)~bits; > > Looks strange that only this use of bits needs the cast? Yes the ~ operator promotes to int. https://en.cppreference.com/w/cpp/language/operator_arithmetic Conversions If the operand passed to an arithmetic operator is integral or unscoped enumeration type, then before any other action (but after lvalue-to-rvalue conversion, if applicable), the operand undergoes [integral promotion](https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion). If an operand has array or function type, [array-to-pointer](https://en.cppreference.com/w/cpp/language/implicit_conversion#array_to_pointer_conversion) and [function-to-pointer](https://en.cppreference.com/w/cpp/language/implicit_conversion#function_to_pointer) conversions are applied. For the binary operators (except shifts), if the promoted operands have different types, [usual arithmetic conversions](https://en.cppreference.com/w/cpp/language/usual_arithmetic_conversions) are applied. char, signed char, unsigned char, short and unsigned short can be converted to int if their respective entire value range can be held by the type int, or unsigned int otherwise; > src/hotspot/share/prims/jvmtiTrace.cpp line 234: > >> 232: _event_trace_flags[i] |= bits; >> 233: } else { >> 234: _event_trace_flags[i] &= (jbyte)~bits; > > Looks strange that only this use of bits needs the cast? Same - the ~ operator promotes to int. > src/hotspot/share/runtime/jfieldIDWorkaround.hpp line 87: > >> 85: return ((as_uint & checked_mask_in_place) != 0); >> 86: } >> 87: static int raw_instance_offset(jfieldID id) { > > This doesn't look right as we've gone from returning a 64-bit value to a > 32-bit value. If it is meant to be only 32-bit I expect the callers need some > adjustment too. static jfieldID to_instance_jfieldID(Klass* k, int offset) { We encode the offset as an int so to get the offset back again, it should be an int. I worked out the calculation once but I could just check_cast<int> the 1 jvmti caller instead, and save the 7 jni callers for another pass. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247783660 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247833600 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247784556 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247833066 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247784903 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247825020 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247826857 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247788982 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247793928 PR Review Comment: https://git.openjdk.org/jdk/pull/14710#discussion_r1247802771