mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
Merge
This commit is contained in:
commit
930f116ae7
83 changed files with 1572 additions and 1569 deletions
|
@ -1965,20 +1965,7 @@ public final class String
|
|||
if (str.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
if (coder() == str.coder()) {
|
||||
byte[] val = this.value;
|
||||
byte[] oval = str.value;
|
||||
int len = val.length + oval.length;
|
||||
byte[] buf = Arrays.copyOf(val, len);
|
||||
System.arraycopy(oval, 0, buf, val.length, oval.length);
|
||||
return new String(buf, coder);
|
||||
}
|
||||
int len = length();
|
||||
int olen = str.length();
|
||||
byte[] buf = StringUTF16.newBytesFor(len + olen);
|
||||
getBytes(buf, 0, UTF16);
|
||||
str.getBytes(buf, len, UTF16);
|
||||
return new String(buf, UTF16);
|
||||
return StringConcatHelper.simpleConcat(this, str);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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,6 +25,9 @@
|
|||
|
||||
package java.lang;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
/**
|
||||
* Helper for string concatenation. These methods are mostly looked up with private lookups
|
||||
* from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
|
||||
|
@ -38,8 +41,10 @@ final class StringConcatHelper {
|
|||
|
||||
/**
|
||||
* Check for overflow, throw exception on overflow.
|
||||
* @param lengthCoder String length and coder
|
||||
* @return lengthCoder
|
||||
*
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @return the given parameter value, if valid
|
||||
*/
|
||||
private static long checkOverflow(long lengthCoder) {
|
||||
if ((int)lengthCoder >= 0) {
|
||||
|
@ -50,76 +55,83 @@ final class StringConcatHelper {
|
|||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, boolean value) {
|
||||
return checkOverflow(current + (value ? 4 : 5));
|
||||
static long mix(long lengthCoder, boolean value) {
|
||||
return checkOverflow(lengthCoder + (value ? 4 : 5));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, byte value) {
|
||||
return mix(current, (int)value);
|
||||
static long mix(long lengthCoder, byte value) {
|
||||
return mix(lengthCoder, (int)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, char value) {
|
||||
return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
|
||||
static long mix(long lengthCoder, char value) {
|
||||
return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, short value) {
|
||||
return mix(current, (int)value);
|
||||
static long mix(long lengthCoder, short value) {
|
||||
return mix(lengthCoder, (int)value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, int value) {
|
||||
return checkOverflow(current + Integer.stringSize(value));
|
||||
static long mix(long lengthCoder, int value) {
|
||||
return checkOverflow(lengthCoder + Integer.stringSize(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, long value) {
|
||||
return checkOverflow(current + Long.stringSize(value));
|
||||
static long mix(long lengthCoder, long value) {
|
||||
return checkOverflow(lengthCoder + Long.stringSize(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix value length and coder into current length and coder.
|
||||
* @param current current length
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
* @param lengthCoder String length with coder packed into higher bits
|
||||
* the upper word.
|
||||
* @param value value to mix in
|
||||
* @return new length and coder
|
||||
*/
|
||||
static long mix(long current, String value) {
|
||||
current += value.length();
|
||||
static long mix(long lengthCoder, String value) {
|
||||
lengthCoder += value.length();
|
||||
if (value.coder() == String.UTF16) {
|
||||
current |= UTF16;
|
||||
lengthCoder |= UTF16;
|
||||
}
|
||||
return checkOverflow(current);
|
||||
return checkOverflow(lengthCoder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -285,10 +297,62 @@ final class StringConcatHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a simple concatenation between two objects. Added for startup
|
||||
* performance, but also demonstrates the code that would be emitted by
|
||||
* {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy}
|
||||
* for two Object arguments.
|
||||
*
|
||||
* @param first first argument
|
||||
* @param second second argument
|
||||
* @return String resulting string
|
||||
*/
|
||||
@ForceInline
|
||||
static String simpleConcat(Object first, Object second) {
|
||||
String s1 = stringOf(first);
|
||||
String s2 = stringOf(second);
|
||||
// start "mixing" in length and coder or arguments, order is not
|
||||
// important
|
||||
long indexCoder = mix(initialCoder(), s2);
|
||||
indexCoder = mix(indexCoder, s1);
|
||||
byte[] buf = newArray(indexCoder);
|
||||
// prepend each argument in reverse order, since we prepending
|
||||
// from the end of the byte array
|
||||
indexCoder = prepend(indexCoder, buf, s2);
|
||||
indexCoder = prepend(indexCoder, buf, s1);
|
||||
return newString(buf, indexCoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* We need some additional conversion for Objects in general, because
|
||||
* {@code String.valueOf(Object)} may return null. String conversion rules
|
||||
* in Java state we need to produce "null" String in this case, so we
|
||||
* provide a customized version that deals with this problematic corner case.
|
||||
*/
|
||||
static String stringOf(Object value) {
|
||||
String s;
|
||||
return (value == null || (s = value.toString()) == null) ? "null" : s;
|
||||
}
|
||||
|
||||
private static final long LATIN1 = (long)String.LATIN1 << 32;
|
||||
|
||||
private static final long UTF16 = (long)String.UTF16 << 32;
|
||||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
/**
|
||||
* Allocates an uninitialized byte array based on the length and coder information
|
||||
* in indexCoder
|
||||
* @param indexCoder
|
||||
* @return the newly allocated byte array
|
||||
*/
|
||||
@ForceInline
|
||||
static byte[] newArray(long indexCoder) {
|
||||
byte coder = (byte)(indexCoder >> 32);
|
||||
int index = (int)indexCoder;
|
||||
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the initial coder for the String.
|
||||
* @return initial coder, adjusted into the upper half
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
|
@ -191,6 +192,8 @@ public final class StringConcatFactory {
|
|||
*/
|
||||
private static final ProxyClassesDumper DUMPER;
|
||||
|
||||
private static final Class<?> STRING_HELPER;
|
||||
|
||||
static {
|
||||
// In case we need to double-back onto the StringConcatFactory during this
|
||||
// static initialization, make sure we have the reasonable defaults to complete
|
||||
|
@ -202,15 +205,20 @@ public final class StringConcatFactory {
|
|||
// DEBUG = false; // implied
|
||||
// DUMPER = null; // implied
|
||||
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
try {
|
||||
STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
|
||||
} catch (Throwable e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
final String strategy =
|
||||
props.getProperty("java.lang.invoke.stringConcat");
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat");
|
||||
CACHE_ENABLE = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.stringConcat.cache"));
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.cache"));
|
||||
DEBUG = Boolean.parseBoolean(
|
||||
props.getProperty("java.lang.invoke.stringConcat.debug"));
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.debug"));
|
||||
final String dumpPath =
|
||||
props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
|
||||
VM.getSavedProperty("java.lang.invoke.stringConcat.dumpClasses");
|
||||
|
||||
STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
|
||||
CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
|
||||
|
@ -1519,6 +1527,33 @@ public final class StringConcatFactory {
|
|||
|
||||
static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
|
||||
|
||||
// Fast-path two-argument Object + Object concatenations
|
||||
if (recipe.getElements().size() == 2) {
|
||||
// Two object arguments
|
||||
if (mt.parameterCount() == 2 &&
|
||||
!mt.parameterType(0).isPrimitive() &&
|
||||
!mt.parameterType(1).isPrimitive()) {
|
||||
return SIMPLE;
|
||||
}
|
||||
// One element is a constant
|
||||
if (mt.parameterCount() == 1 && !mt.parameterType(0).isPrimitive()) {
|
||||
MethodHandle mh = SIMPLE;
|
||||
// Insert constant element
|
||||
|
||||
// First recipe element is a constant
|
||||
if (recipe.getElements().get(0).getTag() == TAG_CONST &&
|
||||
recipe.getElements().get(1).getTag() != TAG_CONST) {
|
||||
return MethodHandles.insertArguments(mh, 0,
|
||||
recipe.getElements().get(0).getValue());
|
||||
} else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
|
||||
recipe.getElements().get(0).getTag() != TAG_CONST) {
|
||||
return MethodHandles.insertArguments(mh, 1,
|
||||
recipe.getElements().get(1).getValue());
|
||||
}
|
||||
// else... fall-through to slow-path
|
||||
}
|
||||
}
|
||||
|
||||
// Create filters and obtain filtered parameter types. Filters would be used in the beginning
|
||||
// to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
|
||||
// The filtered argument type list is used all over in the combinators below.
|
||||
|
@ -1626,13 +1661,6 @@ public final class StringConcatFactory {
|
|||
return mh;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
private static byte[] newArray(long indexCoder) {
|
||||
byte coder = (byte)(indexCoder >> 32);
|
||||
int index = (int)indexCoder;
|
||||
return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
|
||||
}
|
||||
|
||||
private static MethodHandle prepender(Class<?> cl) {
|
||||
return PREPENDERS.computeIfAbsent(cl, PREPEND);
|
||||
}
|
||||
|
@ -1659,16 +1687,15 @@ public final class StringConcatFactory {
|
|||
}
|
||||
};
|
||||
|
||||
private static final MethodHandle SIMPLE;
|
||||
private static final MethodHandle NEW_STRING;
|
||||
private static final MethodHandle NEW_ARRAY;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
|
||||
private static final ConcurrentMap<Class<?>, MethodHandle> MIXERS;
|
||||
private static final long INITIAL_CODER;
|
||||
static final Class<?> STRING_HELPER;
|
||||
|
||||
static {
|
||||
try {
|
||||
STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
|
||||
MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", long.class);
|
||||
INITIAL_CODER = (long) initCoder.invoke();
|
||||
} catch (Throwable e) {
|
||||
|
@ -1678,8 +1705,9 @@ public final class StringConcatFactory {
|
|||
PREPENDERS = new ConcurrentHashMap<>();
|
||||
MIXERS = new ConcurrentHashMap<>();
|
||||
|
||||
SIMPLE = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "simpleConcat", String.class, Object.class, Object.class);
|
||||
NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, long.class);
|
||||
NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, long.class);
|
||||
NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newArray", byte[].class, long.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1692,22 +1720,8 @@ public final class StringConcatFactory {
|
|||
// no instantiation
|
||||
}
|
||||
|
||||
private static class ObjectStringifier {
|
||||
|
||||
// We need some additional conversion for Objects in general, because String.valueOf(Object)
|
||||
// may return null. String conversion rules in Java state we need to produce "null" String
|
||||
// in this case, so we provide a customized version that deals with this problematic corner case.
|
||||
private static String valueOf(Object value) {
|
||||
String s;
|
||||
return (value == null || (s = value.toString()) == null) ? "null" : s;
|
||||
}
|
||||
|
||||
// Could have used MethodHandles.lookup() instead of Lookup.IMPL_LOOKUP, if not for the fact
|
||||
// java.lang.invoke Lookups are explicitly forbidden to be retrieved using that API.
|
||||
private static final MethodHandle INSTANCE =
|
||||
lookupStatic(Lookup.IMPL_LOOKUP, ObjectStringifier.class, "valueOf", String.class, Object.class);
|
||||
|
||||
}
|
||||
private static final MethodHandle OBJECT_INSTANCE =
|
||||
lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "stringOf", String.class, Object.class);
|
||||
|
||||
private static class FloatStringifiers {
|
||||
private static final MethodHandle FLOAT_INSTANCE =
|
||||
|
@ -1751,7 +1765,7 @@ public final class StringConcatFactory {
|
|||
*/
|
||||
static MethodHandle forMost(Class<?> t) {
|
||||
if (!t.isPrimitive()) {
|
||||
return ObjectStringifier.INSTANCE;
|
||||
return OBJECT_INSTANCE;
|
||||
} else if (t == float.class) {
|
||||
return FloatStringifiers.FLOAT_INSTANCE;
|
||||
} else if (t == double.class) {
|
||||
|
|
|
@ -791,7 +791,7 @@ public abstract class FileChannel
|
|||
// -- Memory-mapped buffers --
|
||||
|
||||
/**
|
||||
* A typesafe enumeration for file-mapping modes.
|
||||
* A file-mapping mode.
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
|
@ -819,6 +819,12 @@ public abstract class FileChannel
|
|||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class. This constructor may be used
|
||||
* by code in java.base to create file mapping modes beyond the file
|
||||
* mapping modes defined here.
|
||||
* @param name the name of the map mode
|
||||
*/
|
||||
private MapMode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -837,8 +843,8 @@ public abstract class FileChannel
|
|||
/**
|
||||
* Maps a region of this channel's file directly into memory.
|
||||
*
|
||||
* <p> A region of a file may be mapped into memory in one of three modes:
|
||||
* </p>
|
||||
* <p> The {@code mode} parameter specifies how the region of the file is
|
||||
* mapped and may be one of the following modes:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
|
@ -859,6 +865,8 @@ public abstract class FileChannel
|
|||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p> An implementation may support additional map modes.
|
||||
*
|
||||
* <p> For a read-only mapping, this channel must have been opened for
|
||||
* reading; for a read/write or private mapping, this channel must have
|
||||
* been opened for both reading and writing.
|
||||
|
@ -892,7 +900,8 @@ public abstract class FileChannel
|
|||
* MapMode#READ_WRITE READ_WRITE}, or {@link MapMode#PRIVATE
|
||||
* PRIVATE} defined in the {@link MapMode} class, according to
|
||||
* whether the file is to be mapped read-only, read/write, or
|
||||
* privately (copy-on-write), respectively
|
||||
* privately (copy-on-write), respectively, or an implementation
|
||||
* specific map mode
|
||||
*
|
||||
* @param position
|
||||
* The position within the file at which the mapped region
|
||||
|
@ -905,25 +914,29 @@ public abstract class FileChannel
|
|||
* @return The mapped byte buffer
|
||||
*
|
||||
* @throws NonReadableChannelException
|
||||
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} but
|
||||
* this channel was not opened for reading
|
||||
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} or
|
||||
* an implementation specific map mode requiring read access
|
||||
* but this channel was not opened for reading
|
||||
*
|
||||
* @throws NonWritableChannelException
|
||||
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE} or
|
||||
* {@link MapMode#PRIVATE PRIVATE} but this channel was not opened
|
||||
* for both reading and writing
|
||||
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE}.
|
||||
* {@link MapMode#PRIVATE PRIVATE} or an implementation specific
|
||||
* map mode requiring write access but this channel was not
|
||||
* opened for both reading and writing
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the preconditions on the parameters do not hold
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If an unsupported map mode is specified
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*
|
||||
* @see java.nio.channels.FileChannel.MapMode
|
||||
* @see java.nio.MappedByteBuffer
|
||||
*/
|
||||
public abstract MappedByteBuffer map(MapMode mode,
|
||||
long position, long size)
|
||||
public abstract MappedByteBuffer map(MapMode mode, long position, long size)
|
||||
throws IOException;
|
||||
|
||||
|
||||
|
|
|
@ -940,14 +940,15 @@ public class FileChannelImpl
|
|||
if (size > Integer.MAX_VALUE)
|
||||
throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
|
||||
|
||||
int imode = -1;
|
||||
int imode;
|
||||
if (mode == MapMode.READ_ONLY)
|
||||
imode = MAP_RO;
|
||||
else if (mode == MapMode.READ_WRITE)
|
||||
imode = MAP_RW;
|
||||
else if (mode == MapMode.PRIVATE)
|
||||
imode = MAP_PV;
|
||||
assert (imode >= 0);
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
if ((mode != MapMode.READ_ONLY) && !writable)
|
||||
throw new NonWritableChannelException();
|
||||
if (!readable)
|
||||
|
|
|
@ -980,7 +980,7 @@ public final class SSLSocketImpl
|
|||
}
|
||||
|
||||
try {
|
||||
shutdownInput(false);
|
||||
SSLSocketImpl.this.close();
|
||||
} catch (IOException ioe) {
|
||||
// ignore the exception
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
|
@ -1146,7 +1146,7 @@ public final class SSLSocketImpl
|
|||
}
|
||||
|
||||
try {
|
||||
shutdownOutput();
|
||||
SSLSocketImpl.this.close();
|
||||
} catch (IOException ioe) {
|
||||
// ignore the exception
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
|
|
|
@ -204,11 +204,14 @@ static jboolean IsWildCardEnabled();
|
|||
*/
|
||||
static jlong threadStackSize = 0; /* stack size of the new thread */
|
||||
static jlong maxHeapSize = 0; /* max heap size */
|
||||
static jlong initialHeapSize = 0; /* inital heap size */
|
||||
static jlong initialHeapSize = 0; /* initial heap size */
|
||||
|
||||
/*
|
||||
* A minimum -Xss stack size suitable for all platforms.
|
||||
*/
|
||||
* A minimum initial-thread stack size suitable for most platforms.
|
||||
* This is the minimum amount of stack needed to load the JVM such
|
||||
* that it can reject a too small -Xss value. If this is too small
|
||||
* JVM initialization would cause a StackOverflowError.
|
||||
*/
|
||||
#ifndef STACK_SIZE_MINIMUM
|
||||
#define STACK_SIZE_MINIMUM (64 * KB)
|
||||
#endif
|
||||
|
@ -934,16 +937,18 @@ AddOption(char *str, void *info)
|
|||
options[numOptions].optionString = str;
|
||||
options[numOptions++].extraInfo = info;
|
||||
|
||||
/*
|
||||
* -Xss is used both by the JVM and here to establish the stack size of the thread
|
||||
* created to launch the JVM. In the latter case we need to ensure we don't go
|
||||
* below the minimum stack size allowed. If -Xss is zero that tells the JVM to use
|
||||
* 'default' sizes (either from JVM or system configuration, e.g. 'ulimit -s' on linux),
|
||||
* and is not itself a small stack size that will be rejected. So we ignore -Xss0 here.
|
||||
*/
|
||||
if (JLI_StrCCmp(str, "-Xss") == 0) {
|
||||
jlong tmp;
|
||||
if (parse_size(str + 4, &tmp)) {
|
||||
threadStackSize = tmp;
|
||||
/*
|
||||
* Make sure the thread stack size is big enough that we won't get a stack
|
||||
* overflow before the JVM startup code can check to make sure the stack
|
||||
* is big enough.
|
||||
*/
|
||||
if (threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
|
||||
if (threadStackSize > 0 && threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
|
||||
threadStackSize = STACK_SIZE_MINIMUM;
|
||||
}
|
||||
}
|
||||
|
@ -2322,38 +2327,38 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize,
|
|||
int argc, char **argv,
|
||||
int mode, char *what, int ret)
|
||||
{
|
||||
|
||||
/*
|
||||
* If user doesn't specify stack size, check if VM has a preference.
|
||||
* Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
|
||||
* return its default stack size through the init args structure.
|
||||
*/
|
||||
if (threadStackSize == 0) {
|
||||
struct JDK1_1InitArgs args1_1;
|
||||
memset((void*)&args1_1, 0, sizeof(args1_1));
|
||||
args1_1.version = JNI_VERSION_1_1;
|
||||
ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
|
||||
if (args1_1.javaStackSize > 0) {
|
||||
threadStackSize = args1_1.javaStackSize;
|
||||
}
|
||||
/*
|
||||
* If the user hasn't specified a non-zero stack size ask the JVM for its default.
|
||||
* A returned 0 means 'use the system default' for a platform, e.g., Windows.
|
||||
* Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
|
||||
* return its default stack size through the init args structure.
|
||||
*/
|
||||
struct JDK1_1InitArgs args1_1;
|
||||
memset((void*)&args1_1, 0, sizeof(args1_1));
|
||||
args1_1.version = JNI_VERSION_1_1;
|
||||
ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
|
||||
if (args1_1.javaStackSize > 0) {
|
||||
threadStackSize = args1_1.javaStackSize;
|
||||
}
|
||||
}
|
||||
|
||||
{ /* Create a new thread to create JVM and invoke main method */
|
||||
JavaMainArgs args;
|
||||
int rslt;
|
||||
JavaMainArgs args;
|
||||
int rslt;
|
||||
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
args.mode = mode;
|
||||
args.what = what;
|
||||
args.ifn = *ifn;
|
||||
args.argc = argc;
|
||||
args.argv = argv;
|
||||
args.mode = mode;
|
||||
args.what = what;
|
||||
args.ifn = *ifn;
|
||||
|
||||
rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
|
||||
/* If the caller has deemed there is an error we
|
||||
* simply return that, otherwise we return the value of
|
||||
* the callee
|
||||
*/
|
||||
return (ret != 0) ? ret : rslt;
|
||||
rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
|
||||
/* If the caller has deemed there is an error we
|
||||
* simply return that, otherwise we return the value of
|
||||
* the callee
|
||||
*/
|
||||
return (ret != 0) ? ret : rslt;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue