Skip to content

Commit

Permalink
[GR-45639] Avoid NPE when build JDK has no source zip.
Browse files Browse the repository at this point in the history
PullRequest: graal/14344
  • Loading branch information
fniephaus committed Apr 17, 2023
2 parents 404f325 + e9ff308 commit 451d5ea
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -69,7 +69,7 @@
*
* The starting point is {@link Source#newBuilder(String, java.io.File)} method.
*
* <h3>Read from an URL</h3>
* <h3>Read from a URL</h3>
*
* One can read remote or in JAR resources using the {@link Source#newBuilder(String, java.net.URL)}
* factory: <br>
Expand Down Expand Up @@ -124,9 +124,9 @@
*
* @see Context#eval(Source) To evaluate sources.
* @see Source#findLanguage(File) To detect a language using a File
* @see Source#findLanguage(URL) To detect a language using an URL.
* @see Source#findLanguage(URL) To detect a language using a URL.
* @see Source#findMimeType(File) To detect a MIME type using a File.
* @see Source#findMimeType(URL) To detect a MIME type using an URL.
* @see Source#findMimeType(URL) To detect a MIME type using a URL.
* @since 19.0
*/
public final class Source {
Expand Down Expand Up @@ -634,7 +634,7 @@ public static String findMimeType(File file) throws IOException {
* Returns the probed MIME type for a given url, or <code>null</code> if no MIME type could be
* resolved. Typically the MIME type is identified using the file extension, connection
* meta-data and/or using it contents. Returns <code>null</code> if the language of the given
* file could not be detected. Probing the language of an URL may require to open a new URL
* file could not be detected. Probing the language of a URL may require to open a new URL
* connection.
*
* @throws IOException if an error opening the url occurred.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1387,12 +1387,7 @@ public Value emitFloatConvert(FloatConvert op, Value inputVal) {
LLVMValueRef convert;
switch (op.getCategory()) {
case FloatingPointToInteger:
/* NaNs are converted to 0 in Java, but are undefined in LLVM */
LLVMValueRef value = getVal(inputVal);
LLVMValueRef isNan = builder.buildCompare(Condition.NE, value, value, true);
LLVMValueRef converted = builder.buildFPToSI(getVal(inputVal), destType);
LLVMValueRef zero = builder.constantInteger(0, LLVMIRBuilder.integerTypeWidth(destType));
convert = builder.buildSelect(isNan, zero, converted);
convert = builder.buildSaturatingFloatingPointToInteger(op, getVal(inputVal));
break;
case IntegerToFloatingPoint:
convert = builder.buildSIToFP(getVal(inputVal), destType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.calc.FloatConvert;
import org.graalvm.compiler.core.common.memory.MemoryOrderMode;

import com.oracle.svm.core.FrameAccess;
Expand All @@ -58,6 +59,7 @@

public class LLVMIRBuilder implements AutoCloseable {
private static final String DEFAULT_INSTR_NAME = "";
private static final LLVMTypeRef[] EMPTY_TYPES = new LLVMTypeRef[0];

private LLVMContextRef context;
private LLVMBuilderRef builder;
Expand Down Expand Up @@ -93,13 +95,17 @@ public void setMainFunction(String functionName, LLVMTypeRef functionType) {
/* Module */

public byte[] getBitcode() {
LLVMMemoryBufferRef buffer = LLVM.LLVMWriteBitcodeToMemoryBuffer(module);
BytePointer start = LLVM.LLVMGetBufferStart(buffer);
int size = NumUtil.safeToInt(LLVM.LLVMGetBufferSize(buffer));
final byte[] bitcode;
final LLVMMemoryBufferRef buffer = LLVM.LLVMWriteBitcodeToMemoryBuffer(module);

byte[] bitcode = new byte[size];
start.get(bitcode, 0, size);
LLVM.LLVMDisposeMemoryBuffer(buffer);
try (BytePointer start = LLVM.LLVMGetBufferStart(buffer)) {
final int size = NumUtil.safeToInt(LLVM.LLVMGetBufferSize(buffer));

bitcode = new byte[size];
start.get(bitcode, 0, size);
} finally {
LLVM.LLVMDisposeMemoryBuffer(buffer);
}
return bitcode;
}

Expand Down Expand Up @@ -424,14 +430,20 @@ public LLVMTypeRef structType(LLVMTypeRef... types) {
}

public static int countElementTypes(LLVMTypeRef structType) {
assert LLVM.LLVMGetTypeKind(structType) == LLVM.LLVMStructTypeKind;

return LLVM.LLVMCountStructElementTypes(structType);
}

private static LLVMTypeRef getTypeAtIndex(LLVMTypeRef structType, int index) {
assert LLVM.LLVMGetTypeKind(structType) == LLVM.LLVMStructTypeKind;

return LLVM.LLVMStructGetTypeAtIndex(structType, index);
}

private static LLVMTypeRef[] getElementTypes(LLVMTypeRef structType) {
assert LLVM.LLVMGetTypeKind(structType) == LLVM.LLVMStructTypeKind;

LLVMTypeRef[] types = new LLVMTypeRef[countElementTypes(structType)];
for (int i = 0; i < types.length; ++i) {
types[i] = getTypeAtIndex(structType, i);
Expand Down Expand Up @@ -461,6 +473,10 @@ public static LLVMTypeRef getReturnType(LLVMTypeRef functionType) {

public static LLVMTypeRef[] getParamTypes(LLVMTypeRef functionType) {
int numParams = LLVM.LLVMCountParamTypes(functionType);
if (numParams == 0) {
return EMPTY_TYPES;
}

PointerPointer<LLVMTypeRef> argTypesPointer = new PointerPointer<>(numParams);
LLVM.LLVMGetParamTypes(functionType, argTypesPointer);
return IntStream.range(0, numParams).mapToObj(i -> argTypesPointer.get(LLVMTypeRef.class, i)).toArray(LLVMTypeRef[]::new);
Expand Down Expand Up @@ -1076,6 +1092,45 @@ public LLVMValueRef buildBswap(LLVMValueRef a) {
return buildIntrinsicOp("bswap", a);
}

// LLVM fptosi instruction returns poison if the input is NaN or outside the integer range.
// However, LLVM llvm.fptosi.sat.* intrinsic functions follow the Java semantics.
public LLVMValueRef buildSaturatingFloatingPointToInteger(FloatConvert op, LLVMValueRef a) {
final LLVMTypeRef retType;
switch (op) {
case F2I:
case D2I:
retType = intType();
break;

case F2L:
case D2L:
retType = longType();
break;

default:
throw shouldNotReachHere("Invalid FloatConvert type: " + op);
}

final LLVMTypeRef argType;
switch (op) {
case F2I:
case F2L:
argType = floatType();
break;

case D2I:
case D2L:
argType = doubleType();
break;

default:
throw shouldNotReachHere("Invalid FloatConvert type: " + op);
}

final String intrinsicName = "llvm.fptosi.sat." + intrinsicType(retType) + "." + intrinsicType(argType);
return buildIntrinsicCall(intrinsicName, functionType(retType, argType), a);
}

private LLVMValueRef buildIntrinsicOp(String name, LLVMTypeRef retType, LLVMValueRef... args) {
String intrinsicName = "llvm." + name + "." + intrinsicType(retType);
LLVMTypeRef intrinsicType = functionType(retType, Arrays.stream(args).map(LLVM::LLVMTypeOf).toArray(LLVMTypeRef[]::new));
Expand Down Expand Up @@ -1163,10 +1218,6 @@ public LLVMValueRef buildPtrToInt(LLVMValueRef value) {
return LLVM.LLVMBuildPtrToInt(builder, value, wordType(), DEFAULT_INSTR_NAME);
}

public LLVMValueRef buildFPToSI(LLVMValueRef value, LLVMTypeRef type) {
return LLVM.LLVMBuildFPToSI(builder, value, type, DEFAULT_INSTR_NAME);
}

public LLVMValueRef buildSIToFP(LLVMValueRef value, LLVMTypeRef type) {
return LLVM.LLVMBuildSIToFP(builder, value, type, DEFAULT_INSTR_NAME);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,11 @@ static URLStreamHandler getURLStreamHandler(String protocol) throws MalformedURL
URLStreamHandler result = URLProtocolsSupport.get(protocol);
if (result == null) {
if (onDemandProtocols.contains(protocol)) {
unsupported("Accessing an URL protocol that was not enabled. The URL protocol " + protocol +
unsupported("Accessing a URL protocol that was not enabled. The URL protocol " + protocol +
" is supported but not enabled by default. It must be enabled by adding the " + enableProtocolsOption + protocol +
" option to the native-image command.");
} else {
unsupported("Accessing an URL protocol that was not enabled. The URL protocol " + protocol +
unsupported("Accessing a URL protocol that was not enabled. The URL protocol " + protocol +
" is not tested and might not work as expected. It can be enabled by adding the " + enableProtocolsOption + protocol +
" option to the native-image command.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ private static void addJDKSources() {
Path javaHomePath = Paths.get("", javaHome);
Path srcZipPath = javaHomePath.resolve("lib").resolve("src.zip");
if (!srcZipPath.toFile().exists()) {
System.out.printf("Warning: Unable to locate JDK sources file '%s'. Source line debug will not be available for JDK classes%n", srcZipPath);
return;
}
try {
Expand Down Expand Up @@ -297,7 +298,13 @@ protected Path tryCacheFile(Path filePath, Class<?> clazz) {
if (moduleName != null) {
for (String specialRootModule : SourceRoots.specialRootModules) {
if (moduleName.equals(specialRootModule)) {
for (Path srcRoot : SourceRoots.specialSrcRoots.get(specialRootModule)) {
// handle this module specially as it has intermediate dirs
List<Path> specialModulePathList = SourceRoots.specialSrcRoots.get(specialRootModule);
// if we have no src.zip then there will be no entry in the hash table
if (specialModulePathList == null) {
break;
}
for (Path srcRoot : specialModulePathList) {
String srcRootGroup = srcRoot.subpath(1, 2).toString().replace(".", filePath.getFileSystem().getSeparator());
if (filePath.toString().startsWith(srcRootGroup)) {
Path sourcePath = extendPath(srcRoot, filePath);
Expand Down Expand Up @@ -362,7 +369,12 @@ protected Path checkCacheFile(Path filePath, Class<?> clazz) {
for (String specialRootModule : SourceRoots.specialRootModules) {
if (moduleName.equals(specialRootModule)) {
// handle this module specially as it has intermediate dirs
for (Path srcRoot : SourceRoots.specialSrcRoots.get(specialRootModule)) {
List<Path> specialModulePathList = SourceRoots.specialSrcRoots.get(specialRootModule);
// if we have no src.zip then there will be no entry in the hash table
if (specialModulePathList == null) {
break;
}
for (Path srcRoot : specialModulePathList) {
String srcRootGroup = srcRoot.subpath(1, 2).toString().replace(".", filePath.getFileSystem().getSeparator());
if (filePath.toString().startsWith(srcRootGroup)) {
Path sourcePath = extendPath(srcRoot, filePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
*
* The starting point is {@link Source#newBuilder(String, TruffleFile)} method.
*
* <h3>Read from an URL</h3>
* <h3>Read from a URL</h3>
*
* One can read remote or in JAR resources using the {@link Source#newBuilder(String, java.net.URL)}
* factory: <br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public class CommonConstants {
public static final String BUILTIN_INSTALLATION_DIR = "/usr/lib/graalvm"; // NOI18N

/**
* Origin of the component. An URL. Used only in directory-based registry of installed
* Origin of the component. A URL. Used only in directory-based registry of installed
* components.
*/
public static final String BUNDLE_ORIGIN_URL = "x-GraalVM-Component-Origin"; // NOI18N
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public interface SoftwareChannel {
interface Factory {
/**
* True, if the channel is willing to handle the URL. URL is passed as a String so that
* custom protocols may be used without registering an URLStreamHandlerFactory.
* custom protocols may be used without registering a URLStreamHandlerFactory.
*
* @param source the definition of the channel including label
* @param input input parameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ public static byte[] computeFileDigest(Path localFile, String digestAlgo) throws
* as relative.
*
* @param pathOrURL path or URL to check.
* @return true, if the path is actually an URL.
* @return true, if the path is actually a URL.
*/
public static boolean isRemotePath(String pathOrURL) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
* <ol>
* <li>{@link #overrideCatalogSpec}, which should be set from {@code -C} or GRAALVM_CATALOG_URL
* environment variable by installer launcher.
* <li>catalog related properties from the release file; each software sources has an URL
* <li>catalog related properties from the release file; each software sources has a URL
* (mandatory), label and potentially parameters.
* <li>component_catalog property, which defines all the software sources in a single property
* </ol>
Expand Down

0 comments on commit 451d5ea

Please sign in to comment.