Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static MethodTypeDesc ofDescriptor(String descriptor) {
* @since 21
*/
static MethodTypeDesc of(ClassDesc returnDesc) {
return new MethodTypeDescImpl(returnDesc, ConstantUtils.EMPTY_CLASSDESC);
return MethodTypeDescImpl.ofTrusted(returnDesc, ConstantUtils.EMPTY_CLASSDESC);
}

/**
Expand Down Expand Up @@ -95,7 +95,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, List<ClassDesc> paramDescs) {
* {@link ClassDesc} for {@code void}
*/
static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
return new MethodTypeDescImpl(returnDesc, paramDescs);
return MethodTypeDescImpl.ofTrusted(returnDesc, paramDescs.clone());
}

/**
Expand Down Expand Up @@ -195,13 +195,7 @@ static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) {
* @return the method type descriptor string
* @jvms 4.3.3 Method Descriptors
*/
default String descriptorString() {
return String.format("(%s)%s",
Stream.of(parameterArray())
.map(ClassDesc::descriptorString)
.collect(Collectors.joining()),
returnType().descriptorString());
}
String descriptorString();

/**
* Returns a human-readable descriptor for this method type, using the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
Expand All @@ -24,13 +24,16 @@
*/
package java.lang.constant;

import jdk.internal.vm.annotation.Stable;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;

import static java.util.Objects.requireNonNull;

Expand All @@ -41,22 +44,38 @@
*/
final class MethodTypeDescImpl implements MethodTypeDesc {
private final ClassDesc returnType;
private final ClassDesc[] argTypes;
private final @Stable ClassDesc[] argTypes;
private @Stable String cachedDescriptorString;

/**
* Constructs a {@linkplain MethodTypeDesc} with the specified return type
* and parameter types
* and a trusted and already-validated parameter types array.
*
* @param returnType a {@link ClassDesc} describing the return type
* @param argTypes {@link ClassDesc}s describing the parameter types
* @param validatedArgTypes {@link ClassDesc}s describing the trusted and validated parameter types
*/
MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] argTypes) {
private MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] validatedArgTypes) {
this.returnType = requireNonNull(returnType);
this.argTypes = requireNonNull(argTypes);
this.argTypes = requireNonNull(validatedArgTypes);
}

/**
* Constructs a {@linkplain MethodTypeDesc} with the specified return type
* and a trusted parameter types array, which will be validated.
*
* @param returnType a {@link ClassDesc} describing the return type
* @param trustedArgTypes {@link ClassDesc}s describing the trusted parameter types
*/
static MethodTypeDescImpl ofTrusted(ClassDesc returnType, ClassDesc[] trustedArgTypes) {
Objects.requireNonNull(returnType);
if (trustedArgTypes.length == 0) // implicit null check
return new MethodTypeDescImpl(returnType, ConstantUtils.EMPTY_CLASSDESC);

for (ClassDesc cr : argTypes)
if (cr.isPrimitive() && cr.descriptorString().equals("V"))
for (ClassDesc cd : trustedArgTypes)
if (cd.isPrimitive() && cd.descriptorString().charAt(0) == 'V') // implicit null check
throw new IllegalArgumentException("Void parameters not permitted");

return new MethodTypeDescImpl(returnType, trustedArgTypes);
}

/**
Expand All @@ -70,9 +89,18 @@ final class MethodTypeDescImpl implements MethodTypeDesc {
*/
static MethodTypeDescImpl ofDescriptor(String descriptor) {
requireNonNull(descriptor);

List<String> types = ConstantUtils.parseMethodDescriptor(descriptor);
ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new);
return new MethodTypeDescImpl(ClassDesc.ofDescriptor(types.get(0)), paramTypes);

int paramCount = types.size() - 1;
var paramTypes = paramCount > 0 ? new ClassDesc[paramCount] : ConstantUtils.EMPTY_CLASSDESC;
for (int i = 0; i < paramCount; i++) {
paramTypes[i] = ClassDesc.ofDescriptor(types.get(i + 1));
}

MethodTypeDescImpl result = ofTrusted(ClassDesc.ofDescriptor(types.getFirst()), paramTypes);
result.cachedDescriptorString = descriptor;
return result;
}

@Override
Expand Down Expand Up @@ -102,14 +130,14 @@ public ClassDesc[] parameterArray() {

@Override
public MethodTypeDesc changeReturnType(ClassDesc returnType) {
return MethodTypeDesc.of(returnType, argTypes);
return new MethodTypeDescImpl(returnType, argTypes);
}

@Override
public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) {
ClassDesc[] newArgs = argTypes.clone();
newArgs[index] = paramType;
return MethodTypeDesc.of(returnType, newArgs);
return ofTrusted(returnType, newArgs);
}

@Override
Expand All @@ -120,18 +148,33 @@ public MethodTypeDesc dropParameterTypes(int start, int end) {
ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)];
System.arraycopy(argTypes, 0, newArgs, 0, start);
System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end);
return MethodTypeDesc.of(returnType, newArgs);
return ofTrusted(returnType, newArgs);
}

@Override
public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) {
if (pos < 0 || pos > argTypes.length)
throw new IndexOutOfBoundsException(pos);

ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length];
System.arraycopy(argTypes, 0, newArgs, 0, pos);
System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length);
System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos);
return MethodTypeDesc.of(returnType, newArgs);

return ofTrusted(returnType, newArgs);
}

@Override
public String descriptorString() {
var desc = this.cachedDescriptorString;
if (desc != null)
return desc;

var sj = new StringJoiner("", "(", ")" + returnType().descriptorString());
for (int i = 0; i < parameterCount(); i++) {
sj.add(parameterType(i).descriptorString());
}
return cachedDescriptorString = sj.toString();
}

@Override
Expand Down
Loading