8040102: Remove all references to Unsafe and definition of anonymous clases from the code

As the catch combinator optimization is now part of java.lang.invoke we don't need to put our own in the boot class path in any configuration anymore. Furthermore, with the completion of the array performance subtask of optimistic typing, we can remove the experimental (commented out) Unsafe accessors in the ArrayData classes

Reviewed-by: attila, jlaskey
This commit is contained in:
Marcus Lagergren 2014-04-18 20:12:21 +02:00
parent 89f65d6006
commit 187399b1fd
14 changed files with 48 additions and 594 deletions

@ -1,266 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2010, 2013, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#best pass rate at test 262 known
TEST262_PASS_AT_LEAST=435
RUN_TEST="true"
RUN_TEST262="true"
RUN_NODE="true"
KEEP_OUTPUT="true"
CLEAN_AND_BUILD_NASHORN="true"
#the stable node version to sync against
NODE_LAST_STABLE=v0.6.18
#parse args
for arg in $*
do
if [ $arg = "--no-test" ]; then
RUN_TEST="false"
echo "**** WARNING - you have disabled 'ant test', which is a minimum checkin requirement..."
elif [ $arg = "--no-262" ]; then
RUN_TEST262="false"
elif [ $arg = "--no-node" ]; then
RUN_NODE="false"
elif [ $arg = "--no-build" ]; then
CLEAN_AND_BUILD_NASHORN="false"
elif [ $arg = "--no-logs" ]; then
KEEP_OUTPUT="false"
fi
done
function lastpart() {
arr=$(echo $1 | tr "/" "\n")
for x in $arr
do
_last=$x
done
echo $_last
}
function check_installed() {
which $1 >/dev/null
if [ $? -ne 0 ]; then
echo "Error $1 not installed: $?"
exit 2
fi
}
check_installed hg
check_installed git
check_installed mv
check_installed git
PWD=$(pwd);
while [ -z $NASHORN_ROOT ]
do
if [ -e $PWD/.hg ]; then
NASHORN_ROOT=${PWD}
break
fi
PWD=$(dirname ${PWD})
done
echo "Nashorn root detected at ${NASHORN_ROOT}"
COMMON_ROOT=$(dirname $NASHORN_ROOT)
echo "Common root is ${COMMON_ROOT}"
echo "Running checkintest..."
ABSOLUTE_NASHORN_HOME=$COMMON_ROOT/$(lastpart $NASHORN_ROOT)
if [ $CLEAN_AND_BUILD_NASHORN != "false" ]; then
echo "Cleaning and building nashorn at $ABSOLUTE_NASHORN_HOME/nashorn..."
$(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant clean >/dev/null 2>/dev/null)
$(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant jar >/dev/null 2>/dev/null)
echo "Done."
fi
function failure_check() {
while read line
do
LINE=$(echo $line | grep "Tests run")
if [ "${LINE}" != "" ]; then
RESULT=$(echo $line | grep "Failures: 0" | grep "Errors: 0")
if [ "${RESULT}" == "" ]; then
TESTNAME=$2
echo "There were errors in ${TESTNAME} : ${LINE}"
exit 1
fi
fi
done < $1
}
function test() {
TEST_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
echo "Running 'ant test' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..."
$(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test >$TEST_OUTPUT)
echo "Done."
failure_check $TEST_OUTPUT
echo "**** SUCCESS: 'ant test' successful"
if [ $KEEP_OUTPUT == "true" ]; then
cp $TEST_OUTPUT ./checkintest.test.log
rm -fr $TEST_OUTPUT
fi
}
if [ $RUN_TEST != "false" ]; then
test;
fi
function test262() {
echo "Running 'ant test262parallel' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..."
TEST262_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
echo "Looking for ${ABSOLUTE_NASHORN_HOME}/test/test262..."
if [ ! -e $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 ]; then
echo "test262 is missing... looking in $COMMON_ROOT..."
if [ ! -e $COMMON_ROOT/test262 ]; then
echo "... not there either... cloning from repo..."
hg clone http://hg.ecmascript.org/tests/test262 $COMMON_ROOT/test262 >/dev/null 2>/dev/null
echo "Done."
fi
echo "Adding soft link ${COMMON_ROOT}/test262 -> ${ABSOLUTE_NASHORN_HOME}/test/test262..."
ln -s $COMMON_ROOT/test262 $ABSOLUTE_NASHORN_HOME/nashorn/test/test262
echo "Done."
fi
echo "Ensuring test262 is up to date..."
$(cd $ABSOLUTE_NASHORN_HOME/nashorn/test/test262; hg pull -u >/dev/null 2>/dev/null)
echo "Done."
echo "Running test262..."
$(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test262parallel > $TEST262_OUTPUT)
FAILED=$(cat $TEST262_OUTPUT|grep "Tests run:"| cut -d ' ' -f 15 |tr -cd '"[[:digit:]]')
if [ $FAILED -gt $TEST262_PASS_AT_LEAST ]; then
echo "FAILURE: There are ${FAILED} failures in test262 and can be no more than ${TEST262_PASS_AT_LEAST}"
cp $TEST262_OUTPUT ./checkintest.test262.log
echo "See ./checkintest.test262.log"
echo "Terminating due to error"
exit 1
elif [ $FAILED -lt $TEST262_PASS_AT_LEAST ]; then
echo "There seem to have been fixes to 262. ${FAILED} < ${TEST262_PASS_AT_LEAST}. Please update limit in bin/checkintest.sh"
fi
echo "**** SUCCESS: Test262 passed with no more than ${TEST262_PASS_AT_LEAST} failures."
if [ $KEEP_OUTPUT == "true" ]; then
cp $TEST262_OUTPUT ./checkintest.test262.log
rm -fr $TEST262_OUTPUT
fi
}
if [ $RUN_TEST262 != "false" ]; then
test262;
fi;
function testnode() {
TESTNODEJAR_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX)
echo "Running node tests..."
#replace node jar properties nashorn with this nashorn
NODEJAR_PROPERTIES=~/nodejar.properties
NODE_HOME=$(cat $NODEJAR_PROPERTIES | grep ^node.home | cut -f2 -d=)
NASHORN_HOME=$(cat $NODEJAR_PROPERTIES | grep ^nashorn.home | cut -f2 -d=)
ABSOLUTE_NODE_HOME=$COMMON_ROOT/$(lastpart $NODE_HOME)
echo "Writing nodejar.properties..."
cat > $NODEJAR_PROPERTIES << EOF
node.home=../node
nashorn.home=../$(lastpart $NASHORN_ROOT)
EOF
echo "Done."
echo "Checking node home ${ABSOLUTE_NODE_HOME}..."
if [ ! -e $ABSOLUTE_NODE_HOME ]; then
echo "Node base dir not found. Cloning node..."
$(cd $COMMON_ROOT; git clone https://github.com/joyent/node.git $(lastpart $NODE_HOME) >/dev/null 2>/dev/null)
echo "Done."
echo "Updating to last stable version ${NODE_LAST_STABLE}..."
$(cd $ABSOLUTE_NODE_HOME; git checkout $NODE_LAST_STABLE >/dev/null 2>/dev/null)
echo "Done."
echo "Running configure..."
$(cd $ABSOLUTE_NODE_HOME; ./configure >/dev/null 2>/dev/null)
echo "Done."
fi
echo "Ensuring node is built..."
#make sure node is built
$(cd $ABSOLUTE_NODE_HOME; make >/dev/null 2>/dev/null)
echo "Done."
NODEJAR_HOME=$COMMON_ROOT/nodejar
if [ ! -e $NODEJAR_HOME ]; then
echo "No node jar home found. cloning from depot..."
$(cd $COMMON_ROOT; hg clone https://hg.kenai.com/hg/nodejs~source nodejar >/dev/null 2>/dev/null)
$(cd $COMMON_ROOT/nodejar; ant >/dev/null)
echo "Done."
echo "Copying node files..."
$(cd $COMMON_ROOT/nodejar; ant copy-node-files >/dev/null 2>/dev/null)
echo "Patching node files..."
$(cd $COMMON_ROOT/nodejar; ant patch-node-files >/dev/null 2>/dev/null)
echo "Done."
fi
echo "Ensuring node.jar is up to date from source depot..."
$(cd $COMMON_ROOT/nodejar; hg pull -u >/dev/null 2>/dev/null)
echo "Done."
echo "Installing nashorn..."
$(cd $COMMON_ROOT/nodejar; ant >/dev/null)
echo "Done."
echo "Running node.jar test..."
$(cd $COMMON_ROOT/nodejar; mvn clean verify >$TESTNODEJAR_OUTPUT)
echo "Done."
failure_check $TESTNODEJAR_OUTPUT
echo "**** SUCCESS: Node test successful."
if [ $KEEP_OUTPUT == "true" ]; then
rm -fr $TESTNODEJAR_OUTPUT
cp $TESTNODEJAR_OUTPUT ./checkintest.nodejar.log
fi
}
if [ $RUN_NODE != "false" ]; then
testnode;
fi;
echo "Finished"

Binary file not shown.

@ -3,18 +3,16 @@
#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
#FLAGS="-Djava.security.manager -Djava.security.policy=../build/nashorn.policy -Dnashorn.debug"
FILENAME="./optimistic_dual_catch_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
FILENAME="./optimistic_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
DIR=..
FAST_CATCH_COMBINATOR=
#$DIR/bin/fastCatchCombinator.jar
NASHORN_JAR=$DIR/dist/nashorn.jar
$JAVA_HOME/bin/java \
$FLAGS \
-ea \
-esa \
-Xbootclasspath/p:$FAST_CATCH_COMBINATOR:$NASHORN_JAR \
-Xbootclasspath/p:$NASHORN_JAR \
-Xms2G -Xmx2G \
-XX:+UnlockCommercialFeatures \
-XX:+FlightRecorder \

@ -0,0 +1,28 @@
#!/bin/sh
#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
FILENAME="./optimistic_noassert_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
DIR=..
NASHORN_JAR=$DIR/dist/nashorn.jar
$JAVA_HOME/bin/java \
$FLAGS \
-Xbootclasspath/p:$NASHORN_JAR \
-Xms2G -Xmx2G \
-XX:+UnlockCommercialFeatures \
-XX:+FlightRecorder \
-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$FILENAME,stackdepth=1024 \
-XX:TypeProfileLevel=222 \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseTypeSpeculation \
-XX:+UseMathExactIntrinsics \
-XX:+UnlockDiagnosticVMOptions \
-cp $CLASSPATH:../build/test/classes/ \
jdk.nashorn.tools.Shell ${@}
#-XX:+ShowHiddenFrames \
#-XX:+PrintOptoAssembly \
#-XX:-TieredCompilation \
#-XX:CICompilerCount=1 \

@ -2,30 +2,25 @@
#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true"
FILENAME="./optimistic_dual_catch_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
DIR=..
FAST_CATCH_COMBINATOR=
#$DIR/bin/fastCatchCombinator.jar
NASHORN_JAR=$DIR/dist/nashorn.jar
$JAVA_HOME/bin/java \
$FLAGS \
-ea \
-esa \
-Xbootclasspath/p:$FAST_CATCH_COMBINATOR:$NASHORN_JAR \
-Xbootclasspath/p:$NASHORN_JAR \
-Xms2G -Xmx2G \
-XX:+UnlockCommercialFeatures \
-XX:TypeProfileLevel=222 \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseTypeSpeculation \
-XX:+UseMathExactIntrinsics \
-XX:+UnlockDiagnosticVMOptions \
-XX:+UseNewCode \
-cp $CLASSPATH:../build/test/classes/ \
jdk.nashorn.tools.Shell ${@}
#-XX:+FlightRecorder \
#-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$FILENAME,stackdepth=1024 \
#-XX:+UseTypeSpeculation \
#-XX:+UseMathExactIntrinsics \
#-XX:+ShowHiddenFrames \
#-XX:+PrintOptoAssembly \
#-XX:-TieredCompilation \

@ -83,6 +83,8 @@
package jdk.internal.dynalink.linker;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@ -91,9 +93,7 @@ import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.CatchExceptionCombinator;
import jdk.internal.dynalink.support.Guards;
import jdk.nashorn.internal.runtime.options.Options;
/**
* Represents a conditionally valid method handle. It is an immutable triple of an invocation method handle, a guard
@ -105,8 +105,6 @@ import jdk.nashorn.internal.runtime.options.Options;
* @author Attila Szegedi
*/
public class GuardedInvocation {
private static final boolean USE_FAST_REWRITE = Options.getBooleanProperty("nashorn.fastrewrite");
private final MethodHandle invocation;
private final MethodHandle guard;
private final Class<? extends Throwable> exception;
@ -417,7 +415,7 @@ public class GuardedInvocation {
final MethodHandle catchGuarded =
exception == null ?
guarded :
catchException(
MH.catchException(
guarded,
exception,
MethodHandles.dropArguments(
@ -437,13 +435,6 @@ public class GuardedInvocation {
return spGuarded;
}
private static MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
if (USE_FAST_REWRITE) {
return CatchExceptionCombinator.catchException(target, exType, handler);
}
return MethodHandles.catchException(target, exType, handler);
}
private static void assertType(final MethodHandle mh, final MethodType type) {
if(!mh.type().equals(type)) {
throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());

@ -1,180 +0,0 @@
package jdk.internal.dynalink.support;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
import jdk.nashorn.internal.runtime.RewriteException;
import sun.misc.Unsafe;
/**
* Generates method handles that combine an invocation and a handler for a {@link RewriteException}. Always immediately
* generates compiled bytecode.
*/
public class CatchExceptionCombinator {
static {
System.err.println("*** Running with fast catch combinator handler ***");
}
private static final Type METHOD_HANDLE_TYPE = Type.getType(MethodHandle.class);
private static final String METHOD_HANDLE_TYPE_NAME = METHOD_HANDLE_TYPE.getInternalName();
private static final String OBJECT_TYPE_NAME = Type.getInternalName(Object.class);
private static final String HANDLER_TYPE_NAME = "java.lang.invoke.CatchExceptionCombinator$MH";
private static final String INVOKE_METHOD_NAME = "invoke";
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final ConcurrentMap<CombinatorParameters, ClassTemplate> handlerClassBytes = new ConcurrentHashMap<>();
private static final class CombinatorParameters {
final MethodType targetType;
final Class<? extends Throwable> exType;
final MethodType handlerType;
CombinatorParameters(final MethodType targetType, final Class<? extends Throwable> exType, MethodType handlerType) {
this.targetType = targetType;
this.exType = exType;
this.handlerType = handlerType;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof CombinatorParameters) {
final CombinatorParameters p = (CombinatorParameters)obj;
return targetType.equals(p.targetType) && exType.equals(p.exType) && handlerType.equals(p.handlerType);
}
return false;
}
@Override
public int hashCode() {
return targetType.hashCode() ^ exType.hashCode() ^ handlerType.hashCode();
}
}
/**
* Catch exception - create combinator
* @param target target
* @param exType type to check for
* @param handler catch handler
* @return target wrapped in catch handler
*/
public static MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
final MethodType targetType = target.type();
final MethodType handlerType = handler.type();
final ClassTemplate classTemplate = handlerClassBytes.computeIfAbsent(
new CombinatorParameters(targetType, exType, handlerType), new Function<CombinatorParameters, ClassTemplate>() {
@Override
public ClassTemplate apply(final CombinatorParameters parameters) {
return generateClassTemplate(parameters);
}
});
return classTemplate.instantiate(target, handler, targetType);
}
private static final class ClassTemplate {
final byte[] bytes;
final int target_cp_index;
final int handler_cp_index;
final int cp_size;
ClassTemplate(final byte[] bytes, final int target_cp_index, final int handler_cp_index, final int cp_size) {
this.bytes = bytes;
this.target_cp_index = target_cp_index;
this.handler_cp_index = handler_cp_index;
this.cp_size = cp_size;
}
MethodHandle instantiate(final MethodHandle target, final MethodHandle handler, final MethodType type) {
final Object[] cpPatch = new Object[cp_size];
cpPatch[target_cp_index] = target;
cpPatch[handler_cp_index] = handler;
final Class<?> handlerClass = UNSAFE.defineAnonymousClass(CatchExceptionCombinator.class, bytes, cpPatch);
try {
return MethodHandles.lookup().findStatic(handlerClass, INVOKE_METHOD_NAME, type);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new AssertionError(e);
}
}
}
private static ClassTemplate generateClassTemplate(final CombinatorParameters combinatorParameters) {
final ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
w.visit(V1_7, ACC_PUBLIC | ACC_SUPER, HANDLER_TYPE_NAME, null, OBJECT_TYPE_NAME, null);
final MethodType targetType = combinatorParameters.targetType;
final Class<? extends Throwable> exType = combinatorParameters.exType;
final String methodDescriptor = targetType.toMethodDescriptorString();
final Class<?> returnType = targetType.returnType();
final MethodType handlerType = combinatorParameters.handlerType;
// NOTE: must use strings as placeholders in the constant pool, even if we'll be replacing them with method handles.
final String targetPlaceholder = "T_PLACEHOLDER";
final String handlerPlaceholder = "H_PLACEHOLDER";
final int target_cp_index = w.newConst(targetPlaceholder);
final int handler_cp_index = w.newConst(handlerPlaceholder);
final InstructionAdapter mv = new InstructionAdapter(w.visitMethod(ACC_PUBLIC | ACC_STATIC, INVOKE_METHOD_NAME, methodDescriptor, null, null));
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
mv.visitCode();
final Label _try = new Label();
final Label _end_try= new Label();
mv.visitLabel(_try);
// Invoke
mv.aconst(targetPlaceholder);
mv.checkcast(METHOD_HANDLE_TYPE);
final Class<?>[] paramTypes = targetType.parameterArray();
for(int i = 0, slot = 0; i < paramTypes.length; ++i) {
final Type paramType = Type.getType(paramTypes[i]);
mv.load(slot, paramType);
slot += paramType.getSize();
}
generateInvokeBasic(mv, methodDescriptor);
final Type asmReturnType = Type.getType(returnType);
mv.areturn(asmReturnType);
mv.visitTryCatchBlock(_try, _end_try, _end_try, Type.getInternalName(exType));
mv.visitLabel(_end_try);
// Handle exception
mv.aconst(handlerPlaceholder);
mv.checkcast(METHOD_HANDLE_TYPE);
mv.swap();
final Class<?>[] handlerParamTypes = handlerType.parameterArray();
for(int i = 1, slot = 0; i < handlerParamTypes.length; ++i) {
final Type paramType = Type.getType(handlerParamTypes[i]);
mv.load(slot, paramType);
slot += paramType.getSize();
}
generateInvokeBasic(mv, handlerType.toMethodDescriptorString());
mv.areturn(asmReturnType);
mv.visitMaxs(0, 0);
mv.visitEnd();
w.visitEnd();
final byte[] bytes = w.toByteArray();
final int cp_size = (((bytes[8] & 0xFF) << 8) | (bytes[9] & 0xFF));
return new ClassTemplate(bytes, target_cp_index, handler_cp_index, cp_size);
}
private static void generateInvokeBasic(final InstructionAdapter mv, final String methodDesc) {
mv.invokevirtual(METHOD_HANDLE_TYPE_NAME, "invokeBasic", methodDesc, false);
}
}

@ -162,7 +162,6 @@ public final class ObjectClassGenerator {
*/
static {
if (!OBJECT_FIELDS_ONLY) {
LOG.warning("Running with primitive fields - there is untested functionality!");
FIELD_TYPES.add(PRIMITIVE_FIELD_TYPE);
} else {
LOG.warning("Running with object fields only - this is a deprecated configuration.");

@ -38,24 +38,16 @@ import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import jdk.internal.dynalink.support.CatchExceptionCombinator;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.options.Options;
/**
* An version of a JavaScript function, native or JavaScript.
* Supports lazily generating a constructor version of the invocation.
*/
final class CompiledFunction {
private static final boolean USE_FAST_REWRITE = Options.getBooleanProperty("nashorn.fastrewrite");
static {
if(USE_FAST_REWRITE && CompiledFunction.class.getClassLoader() != null) {
throw new AssertionError("-Dnashorn.fastrewrite can only be used with Nashorn in boot class path! (Try -Xbootclasspath/p:dist/nashorn.jar )");
}
}
private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
private static final MethodHandle RELINK_COMPOSABLE_INVOKER = findOwnMH("relinkComposableInvoker", void.class, CallSite.class, CompiledFunction.class, boolean.class);
@ -548,9 +540,6 @@ final class CompiledFunction {
if(isOptimistic) {
assert handleRewriteException != null;
final MethodHandle typedHandleRewriteException = changeReturnType(handleRewriteException, inv.type().returnType());
if(USE_FAST_REWRITE) {
return CatchExceptionCombinator.catchException(inv, RewriteException.class, typedHandleRewriteException);
}
return MH.catchException(inv, RewriteException.class, typedHandleRewriteException);
}
return inv;

@ -39,31 +39,11 @@ import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import sun.misc.Unsafe;
/**
* ArrayData - abstraction for wrapping array elements
*/
public abstract class ArrayData {
/**
* Unsafe instance used for unsafe array getters (de facto always safe as they are guarded
* by {@link ArrayData#has(int)} anyway
*/
protected static final Unsafe UNSAFE = null;
/* static {
@SuppressWarnings("unused")
Unsafe unsafe = null;
try {
unsafe = Unsafe.getUnsafe();
} catch (final SecurityException e) {
System.err.println("WARNING: Disabling unsafe array getters... Unsafe not available");
}
//TODO: disabled for now as we have seen no real performance improvement on non-micros
//and using UNSAFE is a damn stupid thing to do
UNSAFE = unsafe;
}*/
/** Minimum chunk size for underlying arrays */
protected static final int CHUNK_SIZE = 32;
@ -417,7 +397,7 @@ public abstract class ArrayData {
* @param programPoint program point
* @return the value
*/
public int getIntOptimistic(int index, int programPoint) {
public int getIntOptimistic(final int index, final int programPoint) {
throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
}
@ -437,7 +417,7 @@ public abstract class ArrayData {
* @param programPoint program point
* @return the value
*/
public long getLongOptimistic(int index, int programPoint) {
public long getLongOptimistic(final int index, final int programPoint) {
throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
}
@ -457,7 +437,7 @@ public abstract class ArrayData {
* @param programPoint program point
* @return the value
*/
public double getDoubleOptimistic(int index, int programPoint) {
public double getDoubleOptimistic(final int index, final int programPoint) {
throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
}

@ -65,19 +65,8 @@ final class IntArrayData extends ContinuousArrayData {
this.array = array;
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, UNSAFE == null ? "getElem" : "getElemUnsafe", int.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, UNSAFE == null ? "setElem" : "setElemUnsafe", void.class, int.class, int.class).methodHandle();
private final static long UNSAFE_BASE = UNSAFE == null ? 0L : UNSAFE.arrayBaseOffset(int[].class);
private final static long UNSAFE_SCALE = UNSAFE == null ? 0L : UNSAFE.arrayIndexScale(int[].class);
@SuppressWarnings("unused")
private int getElemUnsafe(final int index) {
if (has(index)) {
return UNSAFE.getInt(array, UNSAFE_BASE + UNSAFE_SCALE * index);
}
throw new ClassCastException();
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
@SuppressWarnings("unused")
private int getElem(final int index) {
@ -87,15 +76,6 @@ final class IntArrayData extends ContinuousArrayData {
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElemUnsafe(final int index, final int elem) {
if (hasRoomFor(index)) {
UNSAFE.putInt(array, UNSAFE_BASE + UNSAFE_SCALE * index, elem);
return;
}
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElem(final int index, final int elem) {
if (hasRoomFor(index)) {

@ -188,19 +188,8 @@ final class LongArrayData extends ContinuousArrayData {
return Type.LONG;
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, UNSAFE == null ? "getElem" : "getElemUnsafe", long.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, UNSAFE == null ? "setElem" : "setElemUnsafe", void.class, int.class, long.class).methodHandle();
private final static long UNSAFE_BASE = UNSAFE == null ? 0L : UNSAFE.arrayBaseOffset(long[].class);
private final static long UNSAFE_SCALE = UNSAFE == null ? 0L : UNSAFE.arrayIndexScale(long[].class);
@SuppressWarnings("unused")
private long getElemUnsafe(final int index) {
if (has(index)) {
return UNSAFE.getLong(array, UNSAFE_BASE + UNSAFE_SCALE * index);
}
throw new ClassCastException();
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
@SuppressWarnings("unused")
private long getElem(final int index) {
@ -210,15 +199,6 @@ final class LongArrayData extends ContinuousArrayData {
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElemUnsafe(final int index, final long elem) {
if (hasRoomFor(index)) {
UNSAFE.putLong(array, UNSAFE_BASE + UNSAFE_SCALE * index, elem);
return;
}
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElem(final int index, final long elem) {
if (hasRoomFor(index)) {

@ -168,19 +168,8 @@ final class NumberArrayData extends ContinuousArrayData {
return Type.NUMBER;
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, UNSAFE == null ? "getElem" : "getElemUnsafe", double.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, UNSAFE == null ? "setElem" : "setElemUnsafe", void.class, int.class, double.class).methodHandle();
private final static long UNSAFE_BASE = UNSAFE == null ? 0L : UNSAFE.arrayBaseOffset(double[].class);
private final static long UNSAFE_SCALE = UNSAFE == null ? 0L : UNSAFE.arrayIndexScale(double[].class);
@SuppressWarnings("unused")
private double getElemUnsafe(final int index) {
if (has(index)) {
return UNSAFE.getDouble(array, UNSAFE_BASE + UNSAFE_SCALE * index);
}
throw new ClassCastException();
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
@SuppressWarnings("unused")
private double getElem(final int index) {
@ -190,15 +179,6 @@ final class NumberArrayData extends ContinuousArrayData {
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElemUnsafe(final int index, final double elem) {
if (hasRoomFor(index)) {
UNSAFE.putDouble(array, UNSAFE_BASE + UNSAFE_SCALE * index, elem);
return;
}
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElem(final int index, final double elem) {
if (hasRoomFor(index)) {

@ -161,19 +161,8 @@ final class ObjectArrayData extends ContinuousArrayData {
return Type.OBJECT;
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, UNSAFE == null ? "getElem" : "getElemUnsafe", Object.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, UNSAFE == null ? "setElem" : "setElemUnsafe", void.class, int.class, Object.class).methodHandle();
private final static long UNSAFE_BASE = UNSAFE == null ? 0L : UNSAFE.arrayBaseOffset(Object[].class);
private final static long UNSAFE_SCALE = UNSAFE == null ? 0L : UNSAFE.arrayIndexScale(Object[].class);
@SuppressWarnings("unused")
private Object getElemUnsafe(final int index) {
if (has(index)) {
return UNSAFE.getObject(array, UNSAFE_BASE + UNSAFE_SCALE * index);
}
throw new ClassCastException();
}
private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "getElem", Object.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "setElem", void.class, int.class, Object.class).methodHandle();
@SuppressWarnings("unused")
private Object getElem(final int index) {
@ -183,15 +172,6 @@ final class ObjectArrayData extends ContinuousArrayData {
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElemUnsafe(final int index, final Object elem) {
if (hasRoomFor(index)) {
UNSAFE.putObject(array, UNSAFE_BASE + UNSAFE_SCALE * index, elem);
return;
}
throw new ClassCastException();
}
@SuppressWarnings("unused")
private void setElem(final int index, final Object elem) {
if (hasRoomFor(index)) {