Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary arrayCopy in Kit.readStream #1033

Merged
merged 2 commits into from
Sep 29, 2021
Merged
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
191 changes: 83 additions & 108 deletions src/org/mozilla/javascript/Kit.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,23 @@
import java.io.Reader;
import java.util.Map;

/**
* Collection of utilities
*/

public class Kit
{
public static Class<?> classOrNull(String className)
{
/** Collection of utilities */
public class Kit {
public static Class<?> classOrNull(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException ex) {
} catch (SecurityException ex) {
} catch (LinkageError ex) {
} catch (ClassNotFoundException ex) {
} catch (SecurityException ex) {
} catch (LinkageError ex) {
} catch (IllegalArgumentException e) {
// Can be thrown if name has characters that a class name
// can not contain
}
return null;
}

/**
* Attempt to load the class of the given name. Note that the type parameter
* isn't checked.
*/
public static Class<?> classOrNull(ClassLoader loader, String className)
{
/** Attempt to load the class of the given name. Note that the type parameter isn't checked. */
public static Class<?> classOrNull(ClassLoader loader, String className) {
try {
return loader.loadClass(className);
} catch (ClassNotFoundException ex) {
Expand All @@ -50,23 +41,19 @@ public static Class<?> classOrNull(ClassLoader loader, String className)
return null;
}

static Object newInstanceOrNull(Class<?> cl)
{
static Object newInstanceOrNull(Class<?> cl) {
try {
return cl.newInstance();
} catch (SecurityException x) {
} catch (LinkageError ex) {
} catch (LinkageError ex) {
} catch (InstantiationException x) {
} catch (IllegalAccessException x) {
}
return null;
}

/**
* Check that testClass is accessible from the given loader.
*/
static boolean testIfCanLoadRhinoClasses(ClassLoader loader)
{
/** Check that testClass is accessible from the given loader. */
static boolean testIfCanLoadRhinoClasses(ClassLoader loader) {
Class<?> testClass = ScriptRuntime.ContextFactoryClass;
Class<?> x = Kit.classOrNull(loader, testClass.getName());
if (x != testClass) {
Expand All @@ -80,17 +67,18 @@ static boolean testIfCanLoadRhinoClasses(ClassLoader loader)
}

/**
* If character <code>c</code> is a hexadecimal digit, return
* <code>accumulator</code> * 16 plus corresponding
* number. Otherise return -1.
* If character <code>c</code> is a hexadecimal digit, return <code>accumulator</code> * 16 plus
* corresponding number. Otherise return -1.
*/
public static int xDigitToInt(int c, int accumulator)
{
check: {
public static int xDigitToInt(int c, int accumulator) {
check:
{
// Use 0..9 < A..Z < a..z
if (c <= '9') {
c -= '0';
if (0 <= c) { break check; }
if (0 <= c) {
break check;
}
} else if (c <= 'F') {
if ('A' <= c) {
c -= ('A' - 10);
Expand All @@ -108,12 +96,12 @@ public static int xDigitToInt(int c, int accumulator)
}

/**
* Add <i>listener</i> to <i>bag</i> of listeners.
* The function does not modify <i>bag</i> and return a new collection
* containing <i>listener</i> and all listeners from <i>bag</i>.
* Bag without listeners always represented as the null value.
* <p>
* Usage example:
* Add <i>listener</i> to <i>bag</i> of listeners. The function does not modify <i>bag</i> and
* return a new collection containing <i>listener</i> and all listeners from <i>bag</i>. Bag
* without listeners always represented as the null value.
*
* <p>Usage example:
*
* <pre>
* private volatile Object changeListeners;
*
Expand Down Expand Up @@ -150,22 +138,20 @@ public static int xDigitToInt(int c, int accumulator)
*
* @param listener Listener to add to <i>bag</i>
* @param bag Current collection of listeners.
* @return A new bag containing all listeners from <i>bag</i> and
* <i>listener</i>.
* @return A new bag containing all listeners from <i>bag</i> and <i>listener</i>.
* @see #removeListener(Object bag, Object listener)
* @see #getListener(Object bag, int index)
*/
public static Object addListener(Object bag, Object listener)
{
public static Object addListener(Object bag, Object listener) {
if (listener == null) throw new IllegalArgumentException();
if (listener instanceof Object[]) throw new IllegalArgumentException();

if (bag == null) {
bag = listener;
} else if (!(bag instanceof Object[])) {
bag = new Object[] { bag, listener };
bag = new Object[] {bag, listener};
} else {
Object[] array = (Object[])bag;
Object[] array = (Object[]) bag;
int L = array.length;
// bag has at least 2 elements if it is array
if (L < 2) throw new IllegalArgumentException();
Expand All @@ -179,30 +165,26 @@ public static Object addListener(Object bag, Object listener)
}

/**
* Remove <i>listener</i> from <i>bag</i> of listeners.
* The function does not modify <i>bag</i> and return a new collection
* containing all listeners from <i>bag</i> except <i>listener</i>.
* If <i>bag</i> does not contain <i>listener</i>, the function returns
* <i>bag</i>.
* <p>
* For usage example, see {@link #addListener(Object bag, Object listener)}.
* Remove <i>listener</i> from <i>bag</i> of listeners. The function does not modify <i>bag</i>
* and return a new collection containing all listeners from <i>bag</i> except <i>listener</i>.
* If <i>bag</i> does not contain <i>listener</i>, the function returns <i>bag</i>.
*
* <p>For usage example, see {@link #addListener(Object bag, Object listener)}.
*
* @param listener Listener to remove from <i>bag</i>
* @param bag Current collection of listeners.
* @return A new bag containing all listeners from <i>bag</i> except
* <i>listener</i>.
* @return A new bag containing all listeners from <i>bag</i> except <i>listener</i>.
* @see #addListener(Object bag, Object listener)
* @see #getListener(Object bag, int index)
*/
public static Object removeListener(Object bag, Object listener)
{
public static Object removeListener(Object bag, Object listener) {
if (listener == null) throw new IllegalArgumentException();
if (listener instanceof Object[]) throw new IllegalArgumentException();

if (bag == listener) {
bag = null;
} else if (bag instanceof Object[]) {
Object[] array = (Object[])bag;
Object[] array = (Object[]) bag;
int L = array.length;
// bag has at least 2 elements if it is array
if (L < 2) throw new IllegalArgumentException();
Expand Down Expand Up @@ -231,25 +213,22 @@ public static Object removeListener(Object bag, Object listener)
}

/**
* Get listener at <i>index</i> position in <i>bag</i> or null if
* <i>index</i> equals to number of listeners in <i>bag</i>.
* <p>
* For usage example, see {@link #addListener(Object bag, Object listener)}.
* Get listener at <i>index</i> position in <i>bag</i> or null if <i>index</i> equals to number
* of listeners in <i>bag</i>.
*
* <p>For usage example, see {@link #addListener(Object bag, Object listener)}.
*
* @param bag Current collection of listeners.
* @param index Index of the listener to access.
* @return Listener at the given index or null.
* @see #addListener(Object bag, Object listener)
* @see #removeListener(Object bag, Object listener)
*/
public static Object getListener(Object bag, int index)
{
public static Object getListener(Object bag, int index) {
if (index == 0) {
if (bag == null)
return null;
if (!(bag instanceof Object[]))
return bag;
Object[] array = (Object[])bag;
if (bag == null) return null;
if (!(bag instanceof Object[])) return bag;
Object[] array = (Object[]) bag;
// bag has at least 2 elements if it is array
if (array.length < 2) throw new IllegalArgumentException();
return array[0];
Expand All @@ -258,22 +237,20 @@ public static Object getListener(Object bag, int index)
if (bag == null) throw new IllegalArgumentException();
return null;
}
Object[] array = (Object[])bag;
Object[] array = (Object[]) bag;
// the array access will check for index on its own
return array[1];
} else {
// bag has to array
Object[] array = (Object[])bag;
Object[] array = (Object[]) bag;
int L = array.length;
if (L < 2) throw new IllegalArgumentException();
if (index == L)
return null;
if (index == L) return null;
return array[index];
}
}

static Object initHash(Map<Object,Object> h, Object key, Object initialValue)
{
static Object initHash(Map<Object, Object> h, Object key, Object initialValue) {
synchronized (h) {
Object current = h.get(key);
if (current == null) {
Expand All @@ -285,46 +262,39 @@ static Object initHash(Map<Object,Object> h, Object key, Object initialValue)
return initialValue;
}

private final static class ComplexKey
{
private static final class ComplexKey {
private Object key1;
private Object key2;
private int hash;

ComplexKey(Object key1, Object key2)
{
ComplexKey(Object key1, Object key2) {
this.key1 = key1;
this.key2 = key2;
}

@Override
public boolean equals(Object anotherObj)
{
if (!(anotherObj instanceof ComplexKey))
return false;
ComplexKey another = (ComplexKey)anotherObj;
public boolean equals(Object anotherObj) {
if (!(anotherObj instanceof ComplexKey)) return false;
ComplexKey another = (ComplexKey) anotherObj;
return key1.equals(another.key1) && key2.equals(another.key2);
}

@Override
public int hashCode()
{
public int hashCode() {
if (hash == 0) {
hash = key1.hashCode() ^ key2.hashCode();
}
return hash;
}
}

public static Object makeHashKeyFromPair(Object key1, Object key2)
{
public static Object makeHashKeyFromPair(Object key1, Object key2) {
if (key1 == null) throw new IllegalArgumentException();
if (key2 == null) throw new IllegalArgumentException();
return new ComplexKey(key1, key2);
}

public static String readReader(Reader reader) throws IOException
{
public static String readReader(Reader reader) throws IOException {
try (BufferedReader in = new BufferedReader(reader)) {
char[] cbuf = new char[1024];
StringBuilder sb = new StringBuilder(1024);
Expand All @@ -336,23 +306,34 @@ public static String readReader(Reader reader) throws IOException
}
}

public static byte[] readStream(InputStream is, int initialBufferCapacity)
throws IOException
{
public static byte[] readStream(InputStream is, int initialBufferCapacity) throws IOException {
if (initialBufferCapacity <= 0) {
throw new IllegalArgumentException(
"Bad initialBufferCapacity: "+initialBufferCapacity);
"Bad initialBufferCapacity: " + initialBufferCapacity);
}
byte[] buffer = new byte[initialBufferCapacity];
int cursor = 0;
for (;;) {
for (; ; ) {
int n = is.read(buffer, cursor, buffer.length - cursor);
if (n < 0) { break; }
if (n < 0) {
break;
}
cursor += n;
if (cursor == buffer.length) {
int readahead = -1;
if (cursor == initialBufferCapacity) {
readahead = is.read();
if (readahead < 0) { // Check for EOS
return buffer;
}
}
byte[] tmp = new byte[buffer.length * 2];
System.arraycopy(buffer, 0, tmp, 0, cursor);
buffer = tmp;
if (readahead != -1) {
buffer[cursor++] = (byte) readahead;
readahead = -1;
}
}
}
if (cursor != buffer.length) {
Expand All @@ -364,29 +345,23 @@ public static byte[] readStream(InputStream is, int initialBufferCapacity)
}

/**
* Throws RuntimeException to indicate failed assertion.
* The function never returns and its return type is RuntimeException
* only to be able to write <code>throw Kit.codeBug()</code> if plain
* <code>Kit.codeBug()</code> triggers unreachable code error.
* Throws RuntimeException to indicate failed assertion. The function never returns and its
* return type is RuntimeException only to be able to write <code>throw Kit.codeBug()</code> if
* plain <code>Kit.codeBug()</code> triggers unreachable code error.
*/
public static RuntimeException codeBug()
throws RuntimeException
{
public static RuntimeException codeBug() throws RuntimeException {
RuntimeException ex = new IllegalStateException("FAILED ASSERTION");
// Print stack trace ASAP
ex.printStackTrace(System.err);
throw ex;
}

/**
* Throws RuntimeException to indicate failed assertion.
* The function never returns and its return type is RuntimeException
* only to be able to write <code>throw Kit.codeBug()</code> if plain
* <code>Kit.codeBug()</code> triggers unreachable code error.
* Throws RuntimeException to indicate failed assertion. The function never returns and its
* return type is RuntimeException only to be able to write <code>throw Kit.codeBug()</code> if
* plain <code>Kit.codeBug()</code> triggers unreachable code error.
*/
public static RuntimeException codeBug(String msg)
throws RuntimeException
{
public static RuntimeException codeBug(String msg) throws RuntimeException {
msg = "FAILED ASSERTION: " + msg;
RuntimeException ex = new IllegalStateException(msg);
// Print stack trace ASAP
Expand Down
Loading