changeset 884:4a47b7cfecdf jdk9-b17

Merge
author lana
date Thu, 05 Jun 2014 19:38:45 -0700
parents b9f9529ba775 a43d59738770
children 893c337bc95f d3cc5b704bfe
files bin/checkintest.sh bin/verbose_octane.bat bin/verbose_octane.sh src/jdk/nashorn/internal/codegen/Attr.java src/jdk/nashorn/internal/codegen/FinalizeTypes.java src/jdk/nashorn/internal/codegen/RangeAnalyzer.java src/jdk/nashorn/internal/codegen/types/Range.java src/jdk/nashorn/internal/ir/TemporarySymbols.java src/jdk/nashorn/internal/runtime/DebugLogger.java src/jdk/nashorn/internal/runtime/Logging.java test/script/basic/JDK-8010697.js test/script/basic/JDK-8010697.js.EXPECTED test/script/basic/arraysIntKey.js test/script/basic/arraysIntKey.js.EXPECTED test/script/basic/ranges_disabled.js test/script/basic/ranges_disabled.js.EXPECTED test/script/basic/ranges_enabled.js test/script/basic/ranges_enabled.js.EXPECTED test/script/basic/ranges_payload.js test/script/basic/runsunspider-eager.js test/script/basic/runsunspider-lazy.js test/script/basic/runsunspider-lazy.js.EXPECTED test/script/maptests/property_delete.js
diffstat 1406 files changed, 40588 insertions(+), 20653 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Jun 04 20:20:44 2014 -0700
+++ b/.hgignore	Thu Jun 05 19:38:45 2014 -0700
@@ -13,6 +13,8 @@
 *.clazz
 *.log
 *.orig
+*.rej
+*~
 genfiles.properties
 hotspot.log
 .DS_Store*
--- a/bin/checkintest.sh	Wed Jun 04 20:20:44 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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"
--- a/bin/fixwhitespace.sh	Wed Jun 04 20:20:44 2014 -0700
+++ b/bin/fixwhitespace.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -22,9 +22,16 @@
 # questions.
 #
 
-#convert tabs to spaces
-find . -name "*.java" -exec sed -i "" 's/	/    /g' {} \;
+fix() {
+    #convert tabs to spaces
+    find . -name $1 -exec sed -i "" 's/	/    /g' {} \;
+    #remove trailing whitespace
+    find . -name $1 -exec sed -i "" 's/[ 	]*$//' \{} \;
+}
 
-#remove trailing whitespace
-find . -name "*.java" -exec sed -i "" 's/[ 	]*$//' \{} \;
-
+if [ ! -z $1 ]; then 
+    fix $1;
+else
+    fix "*.java"
+    fix "*.js"
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/run_octane.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Copyright (c) 2010, 2014, 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.
+#
+
+LOG="./octane_$(date|sed "s/ /_/g"|sed "s/:/_/g").log"
+
+run_one() {
+    sh ../bin/runopt.sh -scripting ../test/script/basic/run-octane.js -- $1 --verbose --iterations 25 | tee -a $LOG
+}
+
+if [ -z $1 ]; then 
+
+    run_one "box2d"
+    run_one "code-load"
+    run_one "crypto"
+    run_one "deltablue"
+    run_one "earley-boyer"
+    run_one "gbemu"
+    run_one "mandreel"
+    run_one "navier-stokes"
+    run_one "pdfjs"
+    run_one "raytrace"
+    run_one "regexp"
+    run_one "richards"
+    run_one "splay"
+    run_one "typescript"
+    run_one "zlib"
+
+else
+    run_one $1
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/rundiff.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# do two runs of a script, one optimistic and one pessimistic, expect identical outputs
+# if not, display and error message and a diff
+
+which opendiff >/dev/null
+RES=$?
+if [ $RES = 0 ]; then
+    DIFFTOOL=opendiff
+else
+    DIFFTOOL=diff
+fi
+
+OPTIMISTIC=out_optimistic
+PESSIMISTIC=out_pessimistic
+$JAVA_HOME/bin/java -ea -jar ../dist/nashorn.jar ${@} >$PESSIMISTIC
+$JAVA_HOME/bin/java -ea -Dnashorn.optimistic -jar ../dist/nashorn.jar ${@} >$OPTIMISTIC
+
+if ! diff -q $PESSIMISTIC $OPTIMISTIC >/dev/null ; then
+    echo "Failure! Results are different"
+    echo ""
+    $DIFFTOOL $PESSIMISTIC $OPTIMISTIC
+else
+    echo "OK - Results are identical"
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/runopt.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# Copyright (c) 2010, 2014, 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.
+#
+
+###########################################################################################
+# This is a helper script to evaluate nashorn with optimistic types
+# it produces a flight recording for every run, and uses the best 
+# known flags for performance for the current configration
+###########################################################################################
+
+# Flags to instrument lambdaform computation, caching, interpretation and compilation
+# Default compile threshold for lambdaforms is 30
+#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 to run trusted tests from the Nashorn test suite
+#FLAGS="-Djava.security.manager -Djava.security.policy=../build/nashorn.policy -Dnashorn.debug"
+
+
+# Unique timestamped file name for JFR recordings. For JFR, we also have to
+# crank up the stack cutoff depth to 1024, because of ridiculously long lambda form
+# stack traces.
+#
+# It is also recommended that you go into $JAVA_HOME/jre/lib/jfr/default.jfc and
+# set the "method-sampling-interval" Normal and Maximum sample time as low as you
+# can go (10 ms on most platforms). The default is normally higher. The increased
+# sampling overhead is usually negligible for Nashorn runs, but the data is better
+
+JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr"
+
+
+# Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming
+# that we run the script from the make dir
+DIR=..
+NASHORN_JAR=$DIR/dist/nashorn.jar
+
+
+# The built Nashorn jar is placed first in the bootclasspath to override the JDK
+# nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in
+# nashorn count as system assertions in this configuration
+
+# Type profiling default level is 111, 222 adds some compile time, but is faster
+
+$JAVA_HOME/bin/java \
+$FLAGS \
+-ea \
+-esa \
+-Xbootclasspath/p:$NASHORN_JAR \
+-Xms2G -Xmx2G \
+-XX:TypeProfileLevel=222 \
+-cp $CLASSPATH:../build/test/classes/ \
+jdk.nashorn.tools.Shell ${@}
+
+# Below are flags that may come in handy, but aren't used for default runs
+
+# Testing out new code optimizations using the generic hotspot "new code" parameter
+#-XX:+UnlockDiagnosticVMOptions \
+#-XX:+UseNewCode \
+
+# Flight recorder
+#-XX:+UnlockCommercialFeatures \
+#-XX:+FlightRecorder \
+#-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024 \
+
+
+# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine,
+# keeping this flag around for experimental reasons. Replace + with - to switch it off
+#-XX:+UseTypeSpeculation \
+
+
+# Same with math intrinsics. They should be enabled by default in 8u20 and 9
+#-XX:+UseMathExactIntrinsics \
+
+
+# Add -Dnashorn.time to time the compilation phases.
+#-Dnashorn.time \
+
+
+# Add ShowHiddenFrames to get lambda form internals on the stack traces
+#-XX:+ShowHiddenFrames \
+
+
+# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product,
+# That tired compilation is switched off, for C2 only output and that the number of
+# compiler threads is set to 1 for determinsm.
+#-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \
+
+# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments)
+# -XX:IncreaseFirstTierCompileThresholdAt=XX
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/runopt_noassert.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -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 \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/runopt_nojfr.sh	Thu Jun 05 19:38:45 2014 -0700
@@ -0,0 +1,27 @@
+#!/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"
+
+DIR=..
+NASHORN_JAR=$DIR/dist/nashorn.jar
+
+$JAVA_HOME/bin/java \
+$FLAGS \
+-ea \
+-esa \
+-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:+ShowHiddenFrames \
+#-XX:+PrintOptoAssembly \
+#-XX:-TieredCompilation \
+#-XX:CICompilerCount=1 \
--- a/bin/verbose_octane.bat	Wed Jun 04 20:20:44 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-rem
-rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
-rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-rem 
-rem This code is free software; you can redistribute it and/or modify it
-rem under the terms of the GNU General Public License version 2 only, as
-rem published by the Free Software Foundation.
-rem 
-rem This code is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-rem version 2 for more details (a copy is included in the LICENSE file that
-rem accompanied this code).
-rem 
-rem You should have received a copy of the GNU General Public License version
-rem 2 along with this work; if not, write to the Free Software Foundation,
-rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-rem 
-rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-rem or visit www.oracle.com if you need additional information or have any
-rem questions.
-rem
-@echo off
-
-if "%JAVA_HOME%" neq "" (
-  call :run "%JAVA_HOME%/bin/java"
-) else (
-  call :run java
-)
-goto :EOF
-
-:run
-setlocal
-set NASHORN_JAR=dist/nashorn.jar
-set JVM_FLAGS=-Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -jar %NASHORN_JAR%
-set JVM_FLAGS7=-Xbootclasspath/p:%NASHORN_JAR% %JVM_FLAGS%
-set OCTANE_ARGS=--verbose --iterations 7
-
-%1 -fullversion 2>&1 | findstr /L /C:"version ""1.7"
-if %errorlevel% equ 0 (
-  set CMD=%1 %JVM_FLAGS7%
-) else (
-  %1 -fullversion
-  set CMD=%1 %JVM_FLAGS%
-)
-
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/box2d.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/code-load.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/crypto.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/deltablue.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/gbemu.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/navier-stokes.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/pdfjs.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/raytrace.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/regexp.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/richards.js %OCTANE_ARGS%
-%CMD% test/script/basic/run-octane.js -- test/script/external/octane/splay.js %OCTANE_ARGS%
-endlocal
-goto :EOF
--- a/bin/verbose_octane.sh	Wed Jun 04 20:20:44 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +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.
-#
-
-ITERS=$1
-if [ -z $ITERS ]; then 
-    ITERS=7
-fi
-NASHORN_JAR=dist/nashorn.jar
-JVM_FLAGS="-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+UnlockDiagnosticVMOptions -Dnashorn.unstable.relink.threshold=8 -Xms2G -Xmx2G -XX:+TieredCompilation -server -jar ${NASHORN_JAR}"
-JVM_FLAGS7="-Xbootclasspath/p:${NASHORN_JAR} ${JVM_FLAGS}"
-OCTANE_ARGS="--verbose --iterations ${ITERS}"
-
-BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "navier-stokes.js" "pdfjs.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" )
-# TODO mandreel.js has metaspace issues
-
-if [ ! -z $JAVA7_HOME ]; then	
-    echo "running ${ITERS} iterations with java7 using JAVA_HOME=${JAVA7_HOME}..."
-    for BENCHMARK in "${BENCHMARKS[@]}"
-    do 
-	CMD="${JAVA7_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}"
-	$CMD
-    done
-else
-    echo "no JAVA7_HOME set. skipping java7"
-fi
-
-if [ ! -z $JAVA8_HOME ]; then
-    echo "running ${ITERS} iterations with java8 using JAVA_HOME=${JAVA8_HOME}..."   
-    for BENCHMARK in "${BENCHMARKS[@]}"
-    do 
-	CMD="${JAVA8_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}"
-	$CMD
-    done
-else 
-    echo "no JAVA8_HOME set."
-fi
-
-echo "Done"
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java	Thu Jun 05 19:38:45 2014 -0700
@@ -31,29 +31,29 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.GETTER_PREFIX;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.LIST_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC;
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java	Thu Jun 05 19:38:45 2014 -0700
@@ -32,9 +32,9 @@
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFFIX;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Thu Jun 05 19:38:45 2014 -0700
@@ -319,7 +319,7 @@
             break;
             case FUNCTION: {
                 final Type returnType = Type.getReturnType(javaDesc);
-                if (!isValidJSType(returnType)) {
+                if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) {
                     error("return value of a @Function method should be a valid JS type, found " + returnType);
                 }
                 final Type[] argTypes = Type.getArgumentTypes(javaDesc);
@@ -351,7 +351,7 @@
             break;
             case SPECIALIZED_FUNCTION: {
                 final Type returnType = Type.getReturnType(javaDesc);
-                if (!isValidJSType(returnType)) {
+                if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) {
                     error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType);
                 }
                 final Type[] argTypes = Type.getArgumentTypes(javaDesc);
@@ -371,9 +371,8 @@
                     error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]);
                 }
 
-                final Type returnType = Type.getReturnType(javaDesc);
-                if (!isJavaLangObject(returnType)) {
-                    error("return type of a @Getter method should be Object, found: " + javaDesc);
+                if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
+                    error("return type of getter should not be void");
                 }
             }
             break;
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java	Thu Jun 05 19:38:45 2014 -0700
@@ -413,7 +413,8 @@
         super.visitMethodInsn(INVOKEVIRTUAL,
                     "java/io/PrintStream",
                     "println",
-                    "(Ljava/lang/String;)V", false);
+                    "(Ljava/lang/String;)V",
+                    false);
     }
 
     // print the object on the top of the stack
@@ -426,6 +427,7 @@
         super.visitMethodInsn(INVOKEVIRTUAL,
                     "java/io/PrintStream",
                     "println",
-                    "(Ljava/lang/Object;)V", false);
+                    "(Ljava/lang/Object;)V",
+                    false);
     }
 }
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java	Thu Jun 05 19:38:45 2014 -0700
@@ -31,9 +31,9 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC;
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Thu Jun 05 19:38:45 2014 -0700
@@ -26,9 +26,8 @@
 package jdk.nashorn.internal.tools.nasgen;
 
 import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.Type;
--- a/docs/DEVELOPER_README	Wed Jun 04 20:20:44 2014 -0700
+++ b/docs/DEVELOPER_README	Thu Jun 05 19:38:45 2014 -0700
@@ -737,26 +737,6 @@
 the JRuby project. The default value for this flag is "joni"
 
 
-SYSTEM PROPERTY: -Dnashorn.time
-
-This enables timers for various phases of script compilation. The timers
-will be dumped when the Nashorn process exits. We see a percentage value
-of how much time was spent not executing bytecode (i.e. compilation and
-internal tasks) at the end of the report. 
-
-Here is an example:
-
-[JavaScript Parsing]    61  ms
-[Constant Folding]      11  ms
-[Control Flow Lowering] 26  ms
-[Type Attribution]      81  ms
-[Range Analysis]        0  ms
-[Code Splitting]        29  ms
-[Type Finalization]     19  ms
-[Bytecode Generation]   189  ms
-[Code Installation]     7  ms
-Total runtime: 508 ms (Non-runtime: 423 ms [83%])
-
 ===============
 2. The loggers.
 ===============
@@ -887,6 +867,34 @@
 (Object in the normal case, unless running with the dual field
 representation)
 
+* time
+
+This enables timers for various phases of script compilation. The timers
+will be dumped when the Nashorn process exits. We see a percentage value
+of how much time was spent not executing bytecode (i.e. compilation and
+internal tasks) at the end of the report. 
+
+A finer level than "info" will show individual compilation timings as they
+happen.
+
+Here is an example:
+
+[time] Accumulated complation phase Timings:
+[time] 
+[time] 'JavaScript Parsing'              1076 ms
+[time] 'Constant Folding'                 159 ms
+[time] 'Control Flow Lowering'            303 ms
+[time] 'Program Point Calculation'        282 ms
+[time] 'Builtin Replacement'               71 ms
+[time] 'Code Splitting'                   670 ms
+[time] 'Symbol Assignment'                474 ms
+[time] 'Scope Depth Computation'          249 ms
+[time] 'Optimistic Type Assignment'       186 ms
+[time] 'Local Variable Type Calculation'  526 ms
+[time] 'Bytecode Generation'             5177 ms
+[time] 'Class Installation'              1854 ms
+[time] 
+[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%])
 
 =======================
 3. Undocumented options
@@ -914,11 +922,10 @@
 
 	-cp, -classpath (-cp path. Specify where to find user class files.)
 
-	-co, --compile-only (Compile script without running. Exit after compilation)
+	-co, --compile-only (Compile without running.)
 		param: [true|false]   default: false
 
-	-d, --dump-debug-dir (specify a destination directory to dump class files. 
-                This must be combined with the --compile-only option to work)
+	-d, --dump-debug-dir (specify a destination directory to dump class files.)
 		param: <path>   
 
 	--debug-lines (Generate line number table in .class files.)
@@ -954,10 +961,6 @@
 	-h, -help (Print help for command line flags.)
 		param: [true|false]   default: false
 
-	--lazy-compilation (EXPERIMENTAL: Use lazy code generation strategies - do not compile 
-	                   the entire script at once.)
-		param: [true|false]   default: false
-
 	--loader-per-compile (Create a new class loader per compile.)
 		param: [true|false]   default: true
 
@@ -965,16 +968,16 @@
 		param: <locale>   default: en-US
 
 	--log (Enable logging of a given level for a given number of sub systems. 
-	      [for example: --log=fields:finest,codegen:info])
+	      [for example: --log=fields:finest,codegen:info].)
 		param: <module:level>,*   
 
-	-nj, --no-java (No Java support)
+	-nj, --no-java (Disable Java support.)
 		param: [true|false]   default: false
 
-	-nse, --no-syntax-extensions (No non-standard syntax extensions)
+	-nse, --no-syntax-extensions (Disallow non-standard syntax extensions.)
 		param: [true|false]   default: false
 
-	-nta, --no-typed-arrays (No Typed arrays support)
+	-nta, --no-typed-arrays (Disable typed arrays support.)
 		param: [true|false]   default: false
 
 	--parse-only (Parse without compiling.)
@@ -983,13 +986,15 @@
 	--print-ast (Print abstract syntax tree.)
 		param: [true|false]   default: false
 
-	--print-code (Print bytecode.)
-		param: [true|false]   default: false
+	-pc, --print-code (Print generated bytecode. If a directory is specified, nothing will 
+	                  be dumped to stderr. Also, in that case, .dot files will be generated 
+	                  for all functions or for the function with the specified name only.)
+		param: [dir:<output-dir>,function:<name>]   
 
 	--print-lower-ast (Print lowered abstract syntax tree.)
 		param: [true|false]   default: false
 
-	--print-lower-parse (Print the parse tree after lowering.)
+	-plp, --print-lower-parse (Print the parse tree after lowering.)
 		param: [true|false]   default: false
 
 	--print-mem-usage (Print memory usage of IR after each compile stage.)
@@ -998,7 +1003,7 @@
 	--print-no-newline (Print function will not print new line char.)
 		param: [true|false]   default: false
 
-	--print-parse (Print the parse tree.)
+	-pp, --print-parse (Print the parse tree.)
 		param: [true|false]   default: false
 
 	--print-symbols (Print the symbol table.)
@@ -1007,21 +1012,13 @@
 	-pcs, --profile-callsites (Dump callsite profile data.)
 		param: [true|false]   default: false
 
-	--range-analysis (EXPERIMENTAL: Do range analysis using known compile time types, 
-	                 and try to narrow number types)
-		param: [true|false]   default: false
-
 	-scripting (Enable scripting features.)
 		param: [true|false]   default: false
 
-	--specialize-calls (EXPERIMENTAL: Specialize all or a set of method according
-	                    to callsite parameter types)
-		param: [=function_1,...,function_n]   
-
-	--stderr (Redirect stderr to a filename or to another tty, e.g. stdout)
+	--stderr (Redirect stderr to a filename or to another tty, e.g. stdout.)
 		param: <output console>   
 
-	--stdout (Redirect stdout to a filename or to another tty, e.g. stderr)
+	--stdout (Redirect stdout to a filename or to another tty, e.g. stderr.)
 		param: <output console>   
 
 	-strict (Run scripts in strict mode.)
@@ -1031,7 +1028,7 @@
 		param: <timezone>   default: Europe/Stockholm
 
 	-tcs, --trace-callsites (Enable callsite trace mode. Options are: miss [trace callsite misses] 
-	                        enterexit [trace callsite enter/exit], objects [print object properties])
+	                         enterexit [trace callsite enter/exit], objects [print object properties].)
 		param: [=[option,]*]   
 
 	--verify-code (Verify byte code before running.)
--- a/make/build-benchmark.xml	Wed Jun 04 20:20:44 2014 -0700
+++ b/make/build-benchmark.xml	Thu Jun 05 19:38:45 2014 -0700
@@ -1,384 +1,333 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
- 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.
+    Copyright (c) 2010, 2014, 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.
 -->
-<project name="nashorn-benchmarks" default="all" basedir="..">
 
-  <target name="octane-init" depends="jar">
-    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes pdfjs raytrace regexp richards splay"/>
+
+<project
+    name="nashorn-benchmarks"
+    default="all"
+    basedir=".."
+    xmlns:if="ant:if">
+
+  <!--
+       Below are the octane benchmarks that should be run.
+       The ones that are excluded, as Nashorn currently has
+       some issues with them (functionality or performance)
+       are commented out
+  -->
+
+  <!-- box2d -->
+  <target name="octane-box2d" depends="octane-box2d-nashorn"/>
+  <target name="octane-box2d-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.box2d" runtime="nashorn"/>
+  </target>
+  <target name="octane-box2d-v8" depends="jar">
+    <run-one cond="octane.benchmark.box2d" runtime="v8"/>
+  </target>
+  <target name="octane-box2d-rhino" depends="jar">
+    <run-one cond="octane.benchmark.box2d" runtime="rhino"/>
+  </target>
+
+  <!-- code-load -->
+  <target name="octane-code-load" depends="octane-code-load-nashorn"/>
+  <target name="octane-code-load-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.code-load" runtime="nashorn"/>
+  </target>
+  <target name="octane-code-load-v8" depends="jar">
+    <run-one cond="octane.benchmark.code-load" runtime="v8"/>
+  </target>
+  <target name="octane-code-load-rhino" depends="jar">
+    <run-one cond="octane.benchmark.code-load" runtime="rhino"/>
+  </target>
+
+  <!-- crypto -->
+  <target name="octane-crypto" depends="octane-crypto-nashorn"/>
+  <target name="octane-crypto-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.crypto" runtime="nashorn"/>
+  </target>
+  <target name="octane-crypto-v8" depends="jar">
+    <run-one cond="octane.benchmark.crypto" runtime="v8"/>
+  </target>
+  <target name="octane-crypto-rhino" depends="jar">
+    <run-one cond="octane.benchmark.crypto" runtime="rhino"/>
+  </target>
+
+  <!-- deltablue -->
+  <target name="octane-deltablue" depends="octane-deltablue-nashorn"/>
+  <target name="octane-deltablue-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.deltablue" runtime="nashorn"/>
+  </target>
+  <target name="octane-deltablue-v8" depends="jar">
+    <run-one cond="octane.benchmark.deltablue" runtime="v8"/>
+  </target>
+  <target name="octane-deltablue-rhino" depends="jar">
+    <run-one cond="octane.benchmark.deltablue" runtime="rhino"/>
+  </target>
+
+  <!-- earley-boyer -->
+  <target name="octane-earley-boyer" depends="octane-earley-boyer-nashorn"/>
+  <target name="octane-earley-boyer-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.earley-boyer" runtime="nashorn"/>
+  </target>
+  <target name="octane-earley-boyer-v8" depends="jar">
+    <run-one cond="octane.benchmark.earley-boyer" runtime="v8"/>
+  </target>
+  <target name="octane-earley-boyer-rhino" depends="jar">
+    <run-one cond="octane.benchmark.earley-boyer" runtime="rhino"/>
   </target>
   
-  <!-- ignore benchmarks where rhino crashes -->
-  <target name="octane-init-rhino" depends="jar">
-    <property name="octane-tests" value="box2d code-load crypto deltablue earley-boyer gbemu navier-stokes raytrace regexp richards splay"/>
+  <!-- gbemu -->
+  <target name="octane-gbemu" depends="octane-gbemu-nashorn"/>
+  <target name="octane-gbemu-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.gbemu" runtime="nashorn"/>
+  </target>
+  <target name="octane-gbemu-v8" depends="jar">
+    <run-one cond="octane.benchmark.gbemu" runtime="v8"/>
+  </target>
+  <target name="octane-gbemu-rhino" depends="jar">
+    <run-one cond="octane.benchmark.gbemu" runtime="rhino"/>
   </target>
 
-  <!-- box2d -->
-  <target name="octane-box2d" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="box2d"/>
+  <!-- mandreel -->
+  <target name="octane-mandreel" depends="octane-mandreel-nashorn"/>
+  <target name="octane-mandreel-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.mandreel" runtime="nashorn"/>
+  </target>
+  <target name="octane-mandreel-v8" depends="jar">
+    <run-one cond="octane.benchmark.mandreel" runtime="v8"/>
+  </target>
+  <target name="octane-mandreel-rhino" depends="jar">
+    <run-one cond="octane.benchmark.mandreel" runtime="rhino"/>
+  </target>
+
+  <!-- navier-stokes -->
+  <target name="octane-navier-stokes" depends="octane-navier-stokes-nashorn"/>
+  <target name="octane-navier-stokes-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.navier-stokes" runtime="nashorn"/>
+  </target>
+  <target name="octane-navier-stokes-v8" depends="jar">
+    <run-one cond="octane.benchmark.navier-stokes" runtime="v8"/>
+  </target>
+  <target name="octane-navier-stokes-rhino" depends="jar">
+    <run-one cond="octane.benchmark.navier-stokes" runtime="rhino"/>
+  </target>
+
+  <!-- pdfjs -->
+  <target name="octane-pdfjs" depends="octane-pdfjs-nashorn"/>
+  <target name="octane-pdfjs-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.pdfjs" runtime="nashorn"/>
+  </target>
+  <target name="octane-pdfjs-v8" depends="jar">
+    <run-one cond="octane.benchmark.pdfjs" runtime="v8"/>
+  </target>
+  <target name="octane-pdfjs-rhino" depends="jar">
+    <run-one cond="octane.benchmark.pdfjs" runtime="rhino"/>
+  </target>
+
+  <!-- raytrace -->
+  <target name="octane-raytrace" depends="octane-raytrace-nashorn"/>
+  <target name="octane-raytrace-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.raytrace" runtime="nashorn"/>
+  </target>
+  <target name="octane-raytrace-v8" depends="jar">
+    <run-one cond="octane.benchmark.raytrace" runtime="v8"/>
+  </target>
+  <target name="octane-raytrace-rhino" depends="jar">
+    <run-one cond="octane.benchmark.raytrace" runtime="rhino"/>
+  </target>
+
+  <!-- regexp -->
+  <target name="octane-regexp" depends="octane-regexp-nashorn"/>
+  <target name="octane-regexp-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.regexp" runtime="nashorn"/>
+  </target>
+  <target name="octane-regexp-v8" depends="jar">
+    <run-one cond="octane.benchmark.regexp" runtime="v8"/>
+  </target>
+  <target name="octane-regexp-rhino" depends="jar">
+    <run-one cond="octane.benchmark.regexp" runtime="rhino"/>
+  </target>
+
+  <!-- richards -->
+  <target name="octane-richards" depends="octane-richards-nashorn"/>
+  <target name="octane-richards-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.richards" runtime="nashorn"/>
+  </target>
+  <target name="octane-richards-v8" depends="jar">
+    <run-one cond="octane.benchmark.richards" runtime="v8"/>
+  </target>
+  <target name="octane-richards-rhino" depends="jar">
+    <run-one cond="octane.benchmark.richards" runtime="rhino"/>
+  </target>
+
+  <!-- splay -->
+  <target name="octane-splay" depends="octane-splay-nashorn"/>
+  <target name="octane-splay-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.splay" runtime="nashorn"/>
+  </target>
+  <target name="octane-splay-v8" depends="jar">
+    <run-one cond="octane.benchmark.splay" runtime="v8"/>
+  </target>
+  <target name="octane-splay-rhino" depends="jar">
+    <run-one cond="octane.benchmark.splay" runtime="rhino"/>
+  </target>
+
+  <!-- typescript -->
+  <target name="octane-typescript" depends="octane-typescript-nashorn"/>
+  <target name="octane-typescript-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.typescript" runtime="nashorn"/>
+  </target>
+  <target name="octane-typescript-v8" depends="jar">
+    <run-one cond="octane.benchmark.typescript" runtime="v8"/>
+  </target>
+  <target name="octane-typescript-rhino" depends="jar">
+    <run-one cond="octane.benchmark.typescript" runtime="rhino"/>
+  </target>
+
+  <!-- zlib -->
+  <target name="octane-zlib" depends="octane-zlib-nashorn"/>
+  <target name="octane-zlib-nashorn" depends="jar">
+    <run-one cond="octane.benchmark.zlib" runtime="nashorn"/>
+  </target>
+  <target name="octane-zlib-v8" depends="jar">
+    <run-one cond="octane.benchmark.zlib" runtime="v8"/>
+  </target>
+  <target name="octane-zlib-rhino" depends="jar">
+    <run-one cond="octane.benchmark.zlib" runtime="rhino"/>
+  </target>
+
+  <!--
+      Benchmark runners for one or more benchmarks, single
+      or multiple process
+  -->
+
+  <target name="octane-process-separate" if="${octane-test-sys-prop.separate.process}">
+    <echo message="Running each benchmark in separate processes, starting new JVMs for each."/>
+    <script language="javascript"><![CDATA[
+      var props = [];
+
+      for (var prop in project.getProperties()) {
+        if (prop.startsWith("octane.benchmark.")) {
+          props.push(prop);
+        }
+      }
+
+      //sort benchmark props in alphabetical order by name
+      props.sort(function(a, b) {
+        if (a < b) {
+          return -1;
+        } else if (a > b) {
+          return 1;
+        } else {
+           return 0;
+        }
+      });
+      
+      var runtime = project.getProperty("runtime");
+
+      for (var i in props) {
+        var task = project.createTask("run-one");
+	// workaround for https://issues.apache.org/bugzilla/show_bug.cgi?id=53831, still not fixed
+        if (task.getOwningTarget() == null) {
+	  task.setOwningTarget(self.getOwningTarget());
+	}
+        var prop = props[i];
+        task.setDynamicAttribute("cond", prop);
+        task.setDynamicAttribute("runtime", runtime);
+	task.perform();
+      }
+    ]]></script>
+  </target>
+
+  <target name="octane-process-single" unless="${octane-test-sys-prop.separate.process}">
+    <echo message="Running all benchmarks in the same process."/>
+    <pathconvert property="octane.benchmarks" pathsep=" ">
+      <propertyset>
+    <propertyref prefix="octane.benchmark."/>
+      </propertyset>
+    </pathconvert>
+    <antcall target="run-octane${runtime}">
+      <param name="octane-tests" value="${octane.benchmarks}"/>
     </antcall>
   </target>
 
-  <target name="octane-box2d-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="box2d"/>
-    </antcall>
+  <!--
+       run 'octane' in single or separate processes based on config
+       This uses nashorn as the default runtime
+  -->
+  <target name="octane-nashorn" depends="jar">
+    <property name="runtime" value="nashorn"/>
+    <antcall target="octane-process-separate"/>
+    <antcall target="octane-process-single"/>
   </target>
 
-  <target name="octane-box2d-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="box2d"/>
-    </antcall>
-  </target>
-
-
-  <!-- code-load -->  
-  <target name="octane-code-load" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
-  </target>
-
-  <target name="octane-code-load-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
-  </target>
-
-  <target name="octane-code-load-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
-  </target>
-
-
-  <!-- crypto -->
-  <target name="octane-crypto" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
-  </target>
-
-  <target name="octane-crypto-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
-  </target>
-
-  <target name="octane-crypto-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
-  </target>
-
-
-  <!-- deltablue -->
-  <target name="octane-deltablue" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
-  </target>
-
-  <target name="octane-deltablue-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
-  </target>
-
-  <target name="octane-deltablue-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
-  </target>
-
-
-  <!-- earley-boyer -->
-  <target name="octane-earley-boyer" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
-  </target>
-
-  <target name="octane-earley-boyer-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
-  </target>
-
-  <target name="octane-earley-boyer-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
-  </target>
-
-
-  <!-- gbemu -->  
-  <target name="octane-gbemu" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
-  </target>
-
-  <target name="octane-gbemu-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
-  </target>
-
-  <target name="octane-gbemu-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
-  </target>
-
-
-  <!-- mandreel -->  
-  <target name="octane-mandreel" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
-  </target>
-
-  <target name="octane-mandreel-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
-  </target>
-
-  <target name="octane-mandreel-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
-  </target>
-
-
-  <!-- navier-stokes -->
-  <target name="octane-navier-stokes" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
-  </target>
-
-  <target name="octane-navier-stokes-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
-  </target>
-
-  <target name="octane-navier-stokes-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
-  </target>
-
-
-  <!-- pdfjs -->  
-  <target name="octane-pdfjs" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
-  </target>
-
-  <target name="octane-pdfjs-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
-  </target>
-
-  <target name="octane-pdfjs-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
-  </target>
-
-
-  <!-- raytrace -->
-  <target name="octane-raytrace" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
-  </target>
-
-  <target name="octane-raytrace-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
-  </target>
-
-  <target name="octane-raytrace-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
-  </target>
-
-
-  <!-- regexp -->
-  <target name="octane-regexp" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
-  </target>
-
-  <target name="octane-regexp-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
-  </target>
-
-  <target name="octane-regexp-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
-  </target>
-
-
-  <!-- richards -->
-  <target name="octane-richards" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
-  </target>
-
-  <target name="octane-richards-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
-  </target>
-
-  <target name="octane-richards-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
-  </target>
-
-
-  <!-- splay -->
-  <target name="octane-splay" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
-  </target>
-
-  <target name="octane-splay-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
-  </target>
-
-  <target name="octane-splay-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
-  </target>
-
-  <!-- splay -->
-  <target name="octane-typescript" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="typescript"/>
-    </antcall>
-  </target>
-
-  <target name="octane-typescript-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-typescript" value="typescript"/>
-    </antcall>
-  </target>
-
-  <target name="octane-typescript-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="typescript"/>
-    </antcall>
-  </target>
-
-  <!-- zlib -->
-  <target name="octane-zlib" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="zlib"/>
-    </antcall>
-  </target>
-
-  <target name="octane-zlib-v8" depends="jar">
-    <antcall target="run-octane-v8">
-      <param name="octane-typescript" value="zlib"/>
-    </antcall>
-  </target>
-
-  <target name="octane-zlib-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="zlib"/>
-    </antcall>
-  </target>
-
-  <!-- run octane benchmarks in a single process  -->
-  <target name="octane-single-process" depends="octane-init">
-    <antcall target="run-octane"/>
-  </target>
-
-  <!-- zlib excluded due to missing implementation of 'read' -->
-  <target name="octane-separate-process" depends=
-     "octane-box2d, octane-code-load, octane-crypto, 
-      octane-deltablue, octane-earley-boyer, octane-gbemu,
-      octane-mandreel, octane-navier-stokes, octane-pdfjs, 
-      octane-raytrace, octane-regexp, octane-richards, 
-      octane-splay, octane-typescript"/>
-
-  <target name="--single-process" unless="${octane-test-sys-prop.separate.process}">
-    <antcall target="octane-single-process"/>
-  </target>
-  <target name="--separate-process" if="${octane-test-sys-prop.separate.process}">
-    <antcall target="octane-separate-process"/>
-  </target>
-
-  <!-- run 'octane' in single or separate processes based on config -->
-  <target name="octane" depends="init, --single-process, --separate-process"/>
+  <!-- alias for 'octane' -->
+  <target name="octane" depends="octane-nashorn"/>
 
   <!-- run octane benchmarks using octane as runtime -->
-  <target name="octane-v8" depends="octane-init">
-    <antcall target="run-octane-v8"/>
+  <target name="octane-v8" depends="jar">
+    <property name="runtime" value="v8"/>
+    <antcall target="octane-process-separate"/>
+    <antcall target="octane-process-single"/>
   </target>
 
   <!-- run octane benchmarks using Rhino as runtime -->
-  <target name="octane-rhino" depends="octane-init-rhino">
-    <antcall target="run-octane-rhino"/>
+  <target name="octane-rhino" depends="jar">
+    <property name="runtime" value="rhino"/>
+    <antcall target="octane-process-separate"/>
+    <antcall target="octane-process-single"/>
   </target>
-  
-  <target name="run-octane">
+
+  <macrodef name="run-one">
+    <attribute name="cond"/>
+    <attribute name="runtime" default=""/>
+    <sequential>
+	<antcall target="run-octane-@{runtime}" if:set="@{cond}">
+	  <param name="octane-tests" value="${@{cond}}"/>
+	</antcall>
+    </sequential>
+  </macrodef>
+
+  <target name="run-octane-nashorn">
     <java classname="${nashorn.shell.tool}"
           classpath="${run.test.classpath}"
           fork="true"
           dir=".">
       <jvmarg line="${ext.class.path}"/>
       <jvmarg line="${run.test.jvmargs.octane} -Xms${run.test.xms} -Xmx${run.test.xmx}"/>
+      <!-- pass on all properties prefixed with 'nashorn' to the runtime -->
       <syspropertyset>
         <propertyref prefix="nashorn."/>
       </syspropertyset>
       <arg value="${octane-test-sys-prop.test.js.framework}"/>
+      <arg value="-scripting"/>
       <arg value="--"/>
       <arg value="${octane-tests}"/>
       <arg value="--runtime"/>
-      <arg value="Nashorn"/>
+      <arg value="nashorn"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations ${octane.iterations}"/>
     </java>
   </target>
 
@@ -386,11 +335,11 @@
     <exec executable="${v8.shell}">
       <arg value="${octane-test-sys-prop.test.js.framework}"/>
       <arg value="--"/>
-      <arg value="${octane-tests}"/>      
+      <arg value="${octane-tests}"/>
       <arg value="--runtime"/>
       <arg value="v8"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations ${octane.iterations}"/>
     </exec>
   </target>
 
@@ -400,12 +349,14 @@
           fork="true"
           dir=".">
       <jvmarg line="${run.test.jvmargs.octane} -Xms${run.test.xms} -Xmx${run.test.xmx}"/>
+      <arg value="-opt"/>
+      <arg value="9"/>
       <arg value="${octane-test-sys-prop.test.js.framework}"/>
       <arg value="${octane-tests}"/>
       <arg value="--runtime"/>
-      <arg value="Rhino"/>
+      <arg value="rhino"/>
       <arg value="--verbose"/>
-      <arg value="--iterations 8"/>
+      <arg value="--iterations ${octane.iterations}"/>
     </java>
   </target>
 
@@ -416,18 +367,22 @@
       <arg value="${octane-tests}/"/>
     </exec>
   </target>
-   
+
   <target name="sunspider-init" depends="jar">
     <fileset id="sunspider-set"
-	     dir="${sunspider-test-sys-prop.test.js.roots}"
-	     excludes="${sunspider-test-sys-prop.test.js.exclude.list}">
+         dir="${sunspider-test-sys-prop.test.js.roots}"
+         excludes="${sunspider-test-sys-prop.test.js.exclude.list}">
       <include name="**/*.js"/>
     </fileset>
     <pathconvert pathsep=" " property="sunspider-tests" refid="sunspider-set"/>
   </target>
 
+  <!--- SUNSPIDER JOB BELOW -->
+
   <!-- run sunspider with Nashorn -->
-  <target name="sunspider" depends="sunspider-init">
+  <target name="sunspider" depends="sunspider-nashorn"/>
+
+  <target name="sunspider-nashorn" depends="sunspider-init">
     <java classname="${nashorn.shell.tool}"
           classpath="${run.test.classpath}"
           fork="true"
@@ -439,6 +394,9 @@
       <arg value="${sunspider-test-sys-prop.test.js.framework}"/>
       <arg value="--"/>
       <arg value="${sunspider-tests}/"/>
+      <arg value="--verbose"/>
+      <arg value="--times"/>
+      <arg value="${sunspider.iterations}"/>
     </java>
   </target>
 
@@ -448,6 +406,9 @@
       <arg value="${sunspider-test-sys-prop.test.js.framework}"/>
       <arg value="--"/>
       <arg value="${sunspider-tests}/"/>
+      <arg value="--verbose"/>
+      <arg value="--times"/>
+      <arg value="${sunspider.iterations}"/>
     </exec>
   </target>
 
@@ -458,8 +419,13 @@
           fork="true"
           dir=".">
       <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+      <arg value="-opt"/>
+      <arg value="9"/>
       <arg value="${sunspider-test-sys-prop.test.js.framework}"/>
       <arg value="${sunspider-tests}/"/>
+      <arg value="--verbose"/>
+      <arg value="--times"/>
+      <arg value="${sunspider.iterations}"/>
     </java>
   </target>
 
--- a/make/build.xml	Wed Jun 04 20:20:44 2014 -0700
+++ b/make/build.xml	Thu Jun 05 19:38:45 2014 -0700
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
+
 <!--
  Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -21,12 +22,11 @@
  or visit www.oracle.com if you need additional information or have any
  questions.
 -->
+
 <project name="nashorn" default="test" basedir="..">
   <import file="build-nasgen.xml"/>
-  <import file="build-benchmark.xml"/>
   <import file="code_coverage.xml"/>
 
-
   <target name="init-conditions">
     <!-- loading locally defined resources and properties. NB they owerwrite default ones defined later -->
     <property file="${user.home}/.nashorn.project.local.properties"/>
@@ -51,7 +51,7 @@
     <available property="testng.available" file="${file.reference.testng.jar}"/>
     <!-- check if Jemmy ang testng.jar are avaiable -->
     <condition property="jemmy.jfx.testng.available" value="true">
-      <and> 
+      <and>
         <available file="${file.reference.jemmyfx.jar}"/>
         <available file="${file.reference.jemmycore.jar}"/>
         <available file="${file.reference.jemmyawtinput.jar}"/>
@@ -364,6 +364,7 @@
   </target>
 
   <target name="test" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+    <delete dir="${build.dir}/nashorn_code_cache"/>
     <fileset id="test.classes" dir="${build.test.classes.dir}">
       <include name="**/api/javaaccess/*Test.class"/>
       <include name="**/api/scripting/*Test.class"/>
@@ -395,6 +396,7 @@
           <pathelement path="${run.test.classpath}"/>
       </classpath>
     </testng>
+
     <testng outputdir="${build.nosecurity.test.results.dir}" classfilesetref="test.nosecurity.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
       <jvmarg line="${ext.class.path}"/>
@@ -412,18 +414,6 @@
     </testng>
   </target>
 
-  <target name="test-basicparallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file">
-      <!-- use just build.test.classes.dir to avoid referring to TestNG -->
-      <java classname="${parallel.test.runner}" dir="${basedir}" classpath="${build.test.classes.dir}" failonerror="true" fork="true">
-      <jvmarg line="${ext.class.path}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
-      <syspropertyset>
-          <propertyref prefix="test-sys-prop."/>
-          <mapper type="glob" from="test-sys-prop.*" to="*"/>
-      </syspropertyset>
-      </java>
-  </target>
-
   <target name="check-jemmy.jfx.testng" unless="jemmy.jfx.testng.available">
     <echo message="WARNING: Jemmy or JavaFX or TestNG not available, will not run tests. Please copy testng.jar, JemmyCore.jar, JemmyFX.jar, JemmyAWTInput.jar under test${file.separator}lib directory. And make sure you have jfxrt.jar in ${java.home}${file.separator}lib${file.separator}ext dir."/>
   </target>
@@ -432,15 +422,15 @@
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
     </fileset>
-    
+
     <copy file="${file.reference.jfxrt.jar}" todir="dist"/>
-    
+
     <condition property="jfx.prism.order" value="-Dprism.order=j2d" else=" ">
-		<not>
+        <not>
             <os family="mac"/>
         </not>
-	</condition>
-    
+    </condition>
+
     <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
        verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
       <jvmarg line="${ext.class.path}"/>
@@ -455,7 +445,7 @@
       </classpath>
     </testng>
   </target>
-  
+
   <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
@@ -474,7 +464,7 @@
       </classpath>
     </testng>
   </target>
-  
+
   <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
@@ -514,6 +504,26 @@
     </java>
   </target>
 
+  <target name="testparallel" depends="test-parallel"/>
+
+  <target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+      <!-- use just build.test.classes.dir to avoid referring to TestNG -->
+      <java classname="${parallel.test.runner}" dir="${basedir}"
+        failonerror="true"
+        fork="true">
+      <jvmarg line="${ext.class.path}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+      <classpath>
+          <pathelement path="${run.test.classpath}"/>
+      <pathelement path="${build.test.classes.dir}"/>
+      </classpath>
+      <syspropertyset>
+          <propertyref prefix="test-sys-prop."/>
+          <mapper type="glob" from="test-sys-prop.*" to="*"/>
+      </syspropertyset>
+      </java>
+  </target>
+
   <target name="all" depends="test, docs"
       description="Build, test and generate docs for nashorn"/>
 
@@ -621,7 +631,7 @@
     <mkdir dir="${test.external.dir}/yui"/>
     <get src="http://yui.yahooapis.com/3.5.1/build/yui/yui.js" dest="${test.external.dir}/yui" skipexisting="true" ignoreerrors="true"/>
     <get src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js" dest="${test.external.dir}/yui" skipexisting="true" ignoreerrors="true"/>
-    
+
     <!-- showdown -->
     <mkdir dir="${test.external.dir}/showdown"/>
     <get src="https://raw.github.com/coreyti/showdown/master/src/showdown.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
@@ -642,4 +652,6 @@
 
   <target name="alltests" depends="exit-if-no-testng, externals, update-externals, test, test262parallel, perf"/>
 
+  <import file="build-benchmark.xml"/>
+
 </project>
--- a/make/nbproject/ide-targets.xml	Wed Jun 04 20:20:44 2014 -0700
+++ b/make/nbproject/ide-targets.xml	Thu Jun 05 19:38:45 2014 -0700
@@ -31,9 +31,10 @@
             <classpath path="${run.test.classpath}"/>
         </nbjpdastart>
         <java classname="jdk.nashorn.tools.Shell" classpath="${run.test.classpath}" dir="samples" fork="true">
+	    <jvmarg line="-Dnashorn.optimistic"/>
             <jvmarg line="${ext.class.path}"/> 
             <jvmarg line="${run.test.jvmargs}"/>
-            <arg value="test.js"/>
+            <arg value="../make/str.js"/>
             <jvmarg value="-Xdebug"/>
             <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
         </java>
--- a/make/project.properties	Wed Jun 04 20:20:44 2014 -0700
+++ b/make/project.properties	Thu Jun 05 19:38:45 2014 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2014, 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
@@ -53,6 +53,7 @@
 
 # test classes directory
 build.test.classes.dir=${build.dir}/test/classes
+
 # nashorn test jar - internal tests jar and api tests jar
 nashorn.internal.tests.jar=${build.dir}/nashorn-internal-tests.jar
 nashorn.api.tests.jar=${build.dir}/nashorn-api-tests.jar
@@ -60,6 +61,7 @@
 # test results directory
 build.test.results.dir=${build.dir}/test/reports
 build.nosecurity.test.results.dir=${build.dir}/test/nosecurity/reports
+build.nooptimistic.test.results.dir=${build.dir}/test/nooptimistic/reports
 
 # This directory is removed when the project is cleaned:
 dist.dir=dist
@@ -167,21 +169,14 @@
 # test root for octane
 octane-test-sys-prop.test.js.roots=${test.external.dir}/octane/
 
-# run octane benchmars in separate processes?
+# run octane benchmars in separate processes? (recommended)
 octane-test-sys-prop.separate.process=true
 
 # framework root for octane
 octane-test-sys-prop.test.js.framework=${test.basic.dir}/run-octane.js
 
-# list of tests to be excluded
-# mandreel excluded due to OOM
-octane-test-sys-prop.test.js.exclude.list=\
-    base.js \
-    run.js  \
-    mandreel.js
-
 # test root for sunspider
-sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0/
+sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0.2/
 
 # framework root for sunspider
 sunspider-test-sys-prop.test.js.framework=${test.basic.dir}/runsunspider.js
@@ -197,6 +192,7 @@
 
 # test262 test root
 test262-test-sys-prop.test.js.roots=${test262.suite.dir}
+
 # test262 enable/disable strict mode tests
 test262-test-sys-prop.test.js.enable.strict.mode=true
 
@@ -268,48 +264,113 @@
 run.test.xmx=2G
 run.test.xms=2G
 
+# uncomment this jfr.args to enable light recordings. the stack needs to be cranked up to 1024 frames,
+# or everything will as of the now drown in lambda forms and be cut off.
+#
+#jfr.args=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath="test_suite.jfr",stackdepth=1024 \
+
+jfr.args=
+
 run.test.user.language=tr
 run.test.user.country=TR
 
-run.test.jvmargs.common=-server -XX:+TieredCompilation -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError
-
-#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M
-# -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods
+run.test.jvmargs.common=\
+  -server \
+  -Dfile.encoding=UTF-8 \
+  -Duser.language=${run.test.user.language} \
+  -Duser.country=${run.test.user.country} \
+  ${jfr.args} \
+  -XX:+HeapDumpOnOutOfMemoryError
 
 # turn on assertions for tests
-run.test.jvmargs.main=${run.test.jvmargs.common} -ea
+run.test.jvmargs.main=${run.test.jvmargs.common} -ea -Dnashorn.lazy
 
-#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M  
-run.test.jvmargs.octane.main=${run.test.jvmargs.common}
+# extra jvmargs that might be useful for debugging
+#
+# -XX:+UnlockDiagnosticVMOptions 
+#
+# turn off compressed class pointers in metaspace
+# -XX:-UseCompressedKlassPointers  
+#
+# dump the heap after every GC
+# -XX:+PrintHeapAtGC
+#
+# manually set a metaspace size for class data 
+# -XX:ClassMetaspaceSize=300M
+#
+# print out methods compiled
+# -XX:+PrintCompilation 
+#
+# print all compiled nmethods with oopmaps and lots of other info
+# -XX:+PrintNMethods
 
+# Use best known performance options for octane
+run.test.jvmargs.octane.main=${run.test.jvmargs.common} -Dnashorn.lazy -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode -XX:TypeProfileLevel=222
+
+# Security manager args - make sure that we run with the nashorn.policy that the build creates
 run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
 
 # VM options for script tests with @fork option
 test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}
 
 # path of rhino.jar for benchmarks
-rhino.jar=
+rhino.dir=
+rhino.jar=${rhino.dir}/js.jar
 
 v8.shell=d8
 
+# How many iterations should 'ant octane' run for each
+# benchmark
+octane.iterations=25
+
+# List of octane tests to run, as properties prefixed with
+# "octane.benchmark." mapping to the benchmark name in 
+# the test harness
+#
+# Octane tests that are disabled should have their entire line
+# commented out  Tests may be disabled for functionality reasons when
+# they have bugs or when the runtime doesn't handle them (yet)
+octane.benchmark.box2d=box2d
+#octane.benchmark.code-load=code-load
+octane.benchmark.crypto=crypto
+octane.benchmark.deltablue=deltablue
+octane.benchmark.earley-boyer=earley-boyer
+octane.benchmark.gbemu=gbemu
+octane.benchmark.navier-stokes=navier-stokes
+octane.benchmark.mandreel=mandreel
+octane.benchmark.pdfjs=pdfjs
+octane.benchmark.raytrace=raytrace
+octane.benchmark.regexp=regexp
+octane.benchmark.richards=richards
+octane.benchmark.splay=splay
+#octane.benchmark.typescript=typescript
+#octane.benchmark.zlib=zlib
+
 #path to rhino jar file
 octaneperf-sys-prop.rhino.jar=${rhino.jar}
 
 #timeout for performance tests in minutes
 octaneperf-sys-prop.timeout.value=10
 
-################
-# codecoverage #
-################
-	#enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties
+#how many iterations to run sunspider after warmup
+sunspider.iterations=3000
+
+#################
+# code coverage #
+#################
+
+#enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties
 make.code.coverage=false
-	#type of codecoverage; one of static or dynamic. Now only dynamic is supported
+
+#type of codecoverage; one of static or dynamic. Now only dynamic is supported
 jcov=dynamic
-	#naming of CC results
-	#NB directory specified in the cc.dir will be cleaned up!!!
+
+#naming of CC results
+#NB directory specified in the cc.dir will be cleaned up!!!
 cc.dir=${basedir}/../Codecoverage_Nashorn
 cc.result.file.name=CC_${jcov}_nashorn.xml
-	#dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties
+
+#dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties
 jcov2.lib.dir=${basedir}/../jcov2/lib
 jcov.jar=${jcov2.lib.dir}/jcov.jar
 cc.include=jdk\.nashorn\.*
--- a/src/jdk/internal/dynalink/ChainedCallSite.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/ChainedCallSite.java	Thu Jun 05 19:38:45 2014 -0700
@@ -103,8 +103,27 @@
  * handle is always at the start of the chain.
  */
 public class ChainedCallSite extends AbstractRelinkableCallSite {
-    private static final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class,
-            MethodHandle.class);
+    private static final MethodHandle PRUNE_CATCHES =
+            MethodHandles.insertArguments(
+                    Lookup.findOwnSpecial(
+                            MethodHandles.lookup(),
+                            "prune",
+                            MethodHandle.class,
+                            MethodHandle.class,
+                            boolean.class),
+                    2,
+                    true);
+
+    private static final MethodHandle PRUNE_SWITCHPOINTS =
+            MethodHandles.insertArguments(
+                    Lookup.findOwnSpecial(
+                            MethodHandles.lookup(),
+                            "prune",
+                            MethodHandle.class,
+                            MethodHandle.class,
+                            boolean.class),
+                    2,
+                    false);
 
     private final AtomicReference<LinkedList<GuardedInvocation>> invocations = new AtomicReference<>();
 
@@ -112,7 +131,7 @@
      * Creates a new chained call site.
      * @param descriptor the descriptor for the call site.
      */
-    public ChainedCallSite(CallSiteDescriptor descriptor) {
+    public ChainedCallSite(final CallSiteDescriptor descriptor) {
         super(descriptor);
     }
 
@@ -126,24 +145,26 @@
     }
 
     @Override
-    public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
-        relinkInternal(guardedInvocation, fallback, false);
+    public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+        relinkInternal(guardedInvocation, fallback, false, false);
     }
 
     @Override
-    public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
-        relinkInternal(guardedInvocation, fallback, true);
+    public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) {
+        relinkInternal(guardedInvocation, fallback, true, false);
     }
 
-    private MethodHandle relinkInternal(GuardedInvocation invocation, MethodHandle relink, boolean reset) {
+    private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) {
         final LinkedList<GuardedInvocation> currentInvocations = invocations.get();
         @SuppressWarnings({ "unchecked", "rawtypes" })
         final LinkedList<GuardedInvocation> newInvocations =
             currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone();
 
-        // First, prune the chain of invalidated switchpoints.
-        for(Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
-            if(it.next().hasBeenInvalidated()) {
+        // First, prune the chain of invalidated switchpoints, we always do this
+        // We also remove any catches if the remove catches flag is set
+        for(final Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
+            final GuardedInvocation inv = it.next();
+            if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) {
                 it.remove();
             }
         }
@@ -160,12 +181,13 @@
 
         // prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we
         // rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger.
-        final MethodHandle pruneAndInvoke = makePruneAndInvokeMethod(relink);
+        final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, getPruneSwitchpoints());
+        final MethodHandle pruneAndInvokeCatches      = makePruneAndInvokeMethod(relink, getPruneCatches());
 
         // Fold the new chain
         MethodHandle target = relink;
-        for(GuardedInvocation inv: newInvocations) {
-            target = inv.compose(pruneAndInvoke, target);
+        for(final GuardedInvocation inv: newInvocations) {
+            target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches);
         }
 
         // If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case
@@ -178,14 +200,30 @@
     }
 
     /**
+     * Get the switchpoint pruning function for a chained call site
+     * @return function that removes invalidated switchpoints tied to callsite guard chain and relinks
+     */
+    protected MethodHandle getPruneSwitchpoints() {
+        return PRUNE_SWITCHPOINTS;
+    }
+
+    /**
+     * Get the catch pruning function for a chained call site
+     * @return function that removes all catches tied to callsite guard chain and relinks
+     */
+    protected MethodHandle getPruneCatches() {
+        return PRUNE_CATCHES;
+    }
+
+    /**
      * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
      * chain.
      * @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
      * @return a method handle for prune-and-invoke
      */
-    private MethodHandle makePruneAndInvokeMethod(MethodHandle relink) {
+    private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) {
         // Bind prune to (this, relink)
-        final MethodHandle boundPrune = MethodHandles.insertArguments(PRUNE, 0, this, relink);
+        final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink);
         // Make it ignore all incoming arguments
         final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
         // Invoke prune, then invoke the call site target with original arguments
@@ -193,7 +231,7 @@
     }
 
     @SuppressWarnings("unused")
-    private MethodHandle prune(MethodHandle relink) {
-        return relinkInternal(null, relink, false);
+    private MethodHandle prune(final MethodHandle relink, final boolean catches) {
+        return relinkInternal(null, relink, false, catches);
     }
 }
--- a/src/jdk/internal/dynalink/DefaultBootstrapper.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/DefaultBootstrapper.java	Thu Jun 05 19:38:45 2014 -0700
@@ -117,7 +117,7 @@
      * @param type the method signature at the call site
      * @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
      */
-    public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+    public static CallSite bootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) {
         return bootstrapInternal(caller, name, type);
     }
 
@@ -133,11 +133,11 @@
      * @param type the method signature at the call site
      * @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
      */
-    public static CallSite publicBootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+    public static CallSite publicBootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) {
         return bootstrapInternal(MethodHandles.publicLookup(), name, type);
     }
 
-    private static CallSite bootstrapInternal(MethodHandles.Lookup caller, String name, MethodType type) {
+    private static CallSite bootstrapInternal(final MethodHandles.Lookup caller, final String name, final MethodType type) {
         return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type)));
     }
 }
--- a/src/jdk/internal/dynalink/DynamicLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/DynamicLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -140,7 +140,6 @@
  * @author Attila Szegedi
  */
 public class DynamicLinker {
-
     private static final String CLASS_NAME = DynamicLinker.class.getName();
     private static final String RELINK_METHOD_NAME = "relink";
 
@@ -148,6 +147,7 @@
     private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite";
 
     private final LinkerServices linkerServices;
+    private final GuardedInvocationFilter prelinkFilter;
     private final int runtimeContextArgCount;
     private final boolean syncOnRelink;
     private final int unstableRelinkThreshold;
@@ -156,18 +156,20 @@
      * Creates a new dynamic linker.
      *
      * @param linkerServices the linkerServices used by the linker, created by the factory.
+     * @param prelinkFilter see {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter)}
      * @param runtimeContextArgCount see {@link DynamicLinkerFactory#setRuntimeContextArgCount(int)}
      */
-    DynamicLinker(LinkerServices linkerServices, int runtimeContextArgCount, boolean syncOnRelink,
-            int unstableRelinkThreshold) {
+    DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationFilter prelinkFilter, final int runtimeContextArgCount,
+            final boolean syncOnRelink, final int unstableRelinkThreshold) {
         if(runtimeContextArgCount < 0) {
             throw new IllegalArgumentException("runtimeContextArgCount < 0");
         }
         if(unstableRelinkThreshold < 0) {
             throw new IllegalArgumentException("unstableRelinkThreshold < 0");
         }
+        this.linkerServices = linkerServices;
+        this.prelinkFilter = prelinkFilter;
         this.runtimeContextArgCount = runtimeContextArgCount;
-        this.linkerServices = linkerServices;
         this.syncOnRelink = syncOnRelink;
         this.unstableRelinkThreshold = unstableRelinkThreshold;
     }
@@ -199,7 +201,7 @@
     private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME,
             MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class);
 
-    private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, int relinkCount) {
+    private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) {
         // Make a bound MH of invoke() for this linker and call site
         final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf(
                 relinkCount));
@@ -219,16 +221,15 @@
      * @throws Exception rethrows any exception thrown by the linkers
      */
     @SuppressWarnings("unused")
-    private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
+    private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
         final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
         final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
         final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
         final LinkRequest linkRequest =
-                runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments)
-                        : new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments,
-                                runtimeContextArgCount);
+                runtimeContextArgCount == 0 ?
+                        new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
+                        new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);
 
-        // Find a suitable method handle with a guard
         GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
 
         // None found - throw an exception
@@ -248,6 +249,11 @@
             }
         }
 
+        // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
+        // return type of the invocation to the call site.
+        guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
+        guardedInvocation.getClass(); // null pointer check
+
         int newRelinkCount = relinkCount;
         // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
         // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
--- a/src/jdk/internal/dynalink/DynamicLinkerFactory.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/DynamicLinkerFactory.java	Thu Jun 05 19:38:45 2014 -0700
@@ -102,14 +102,15 @@
 import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider;
 import jdk.internal.dynalink.support.CompositeGuardingDynamicLinker;
 import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.DefaultPrelinkFilter;
 import jdk.internal.dynalink.support.LinkerServicesImpl;
 import jdk.internal.dynalink.support.TypeConverterFactory;
 
 /**
  * A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
  * of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
- * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker}. See
- * {@link DynamicLinker} documentation for tips on how to use this class.
+ * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker} and a
+ * {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on how to use this class.
  *
  * @author Attila Szegedi
  */
@@ -128,6 +129,7 @@
     private int runtimeContextArgCount = 0;
     private boolean syncOnRelink = false;
     private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
+    private GuardedInvocationFilter prelinkFilter;
 
     /**
      * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread
@@ -135,7 +137,7 @@
      *
      * @param classLoader the class loader used for the autodiscovery of available linkers.
      */
-    public void setClassLoader(ClassLoader classLoader) {
+    public void setClassLoader(final ClassLoader classLoader) {
         this.classLoader = classLoader;
         classLoaderExplicitlySet = true;
     }
@@ -149,7 +151,7 @@
      * @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers
      * (this is also the default value).
      */
-    public void setPrioritizedLinkers(List<? extends GuardingDynamicLinker> prioritizedLinkers) {
+    public void setPrioritizedLinkers(final List<? extends GuardingDynamicLinker> prioritizedLinkers) {
         this.prioritizedLinkers =
                 prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers);
     }
@@ -162,7 +164,7 @@
      *
      * @param prioritizedLinkers a list of prioritized linkers.
      */
-    public void setPrioritizedLinkers(GuardingDynamicLinker... prioritizedLinkers) {
+    public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) {
         setPrioritizedLinkers(Arrays.asList(prioritizedLinkers));
     }
 
@@ -173,7 +175,7 @@
      * @param prioritizedLinker the single prioritized linker. Must not be null.
      * @throws IllegalArgumentException if null is passed.
      */
-    public void setPrioritizedLinker(GuardingDynamicLinker prioritizedLinker) {
+    public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) {
         if(prioritizedLinker == null) {
             throw new IllegalArgumentException("prioritizedLinker == null");
         }
@@ -188,7 +190,7 @@
      * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
      * fallback linkers.
      */
-    public void setFallbackLinkers(List<? extends GuardingDynamicLinker> fallbackLinkers) {
+    public void setFallbackLinkers(final List<? extends GuardingDynamicLinker> fallbackLinkers) {
         this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers);
     }
 
@@ -200,7 +202,7 @@
      * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
      * fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used.
      */
-    public void setFallbackLinkers(GuardingDynamicLinker... fallbackLinkers) {
+    public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) {
         setFallbackLinkers(Arrays.asList(fallbackLinkers));
     }
 
@@ -214,7 +216,7 @@
      *
      * @param runtimeContextArgCount the number of language runtime context arguments in call sites.
      */
-    public void setRuntimeContextArgCount(int runtimeContextArgCount) {
+    public void setRuntimeContextArgCount(final int runtimeContextArgCount) {
         if(runtimeContextArgCount < 0) {
             throw new IllegalArgumentException("runtimeContextArgCount < 0");
         }
@@ -227,7 +229,7 @@
      * multithreaded execution of dynamically linked code.
      * @param syncOnRelink true for invoking sync on relink, false otherwise.
      */
-    public void setSyncOnRelink(boolean syncOnRelink) {
+    public void setSyncOnRelink(final boolean syncOnRelink) {
         this.syncOnRelink = syncOnRelink;
     }
 
@@ -238,7 +240,7 @@
      * call sites will never be considered unstable.
      * @see LinkRequest#isCallSiteUnstable()
      */
-    public void setUnstableRelinkThreshold(int unstableRelinkThreshold) {
+    public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) {
         if(unstableRelinkThreshold < 0) {
             throw new IllegalArgumentException("unstableRelinkThreshold < 0");
         }
@@ -246,7 +248,19 @@
     }
 
     /**
-     * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers.
+     * Set the pre-link filter. This is a {@link GuardedInvocationFilter} that will get the final chance to modify the
+     * guarded invocation after it has been created by a component linker and before the dynamic linker links it into
+     * the call site. It is normally used to adapt the return value type of the invocation to the type of the call site.
+     * When not set explicitly, {@link DefaultPrelinkFilter} will be used.
+     * @param prelinkFilter the pre-link filter for the dynamic linker.
+     */
+    public void setPrelinkFilter(final GuardedInvocationFilter prelinkFilter) {
+        this.prelinkFilter = prelinkFilter;
+    }
+
+    /**
+     * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as
+     * the pre-link filter.
      *
      * @return the new dynamic Linker
      */
@@ -275,7 +289,7 @@
         // ... prioritized linkers, ...
         linkers.addAll(prioritizedLinkers);
         // ... filtered discovered linkers, ...
-        for(GuardingDynamicLinker linker: discovered) {
+        for(final GuardingDynamicLinker linker: discovered) {
             if(!knownLinkerClasses.contains(linker.getClass())) {
                 linkers.add(linker);
             }
@@ -300,14 +314,18 @@
         }
 
         final List<GuardingTypeConverterFactory> typeConverters = new LinkedList<>();
-        for(GuardingDynamicLinker linker: linkers) {
+        for(final GuardingDynamicLinker linker: linkers) {
             if(linker instanceof GuardingTypeConverterFactory) {
                 typeConverters.add((GuardingTypeConverterFactory)linker);
             }
         }
 
+        if(prelinkFilter == null) {
+            prelinkFilter = new DefaultPrelinkFilter();
+        }
+
         return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite),
-                runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold);
+                prelinkFilter, runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold);
     }
 
     private static ClassLoader getThreadContextClassLoader() {
@@ -319,9 +337,9 @@
         }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT);
     }
 
-    private static void addClasses(Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
-            List<? extends GuardingDynamicLinker> linkers) {
-        for(GuardingDynamicLinker linker: linkers) {
+    private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
+            final List<? extends GuardingDynamicLinker> linkers) {
+        for(final GuardingDynamicLinker linker: linkers) {
             knownLinkerClasses.add(linker.getClass());
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk/internal/dynalink/GuardedInvocationFilter.java	Thu Jun 05 19:38:45 2014 -0700
@@ -0,0 +1,105 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2009-2013 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are
+       met:
+       * Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the copyright holder nor the names of
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
+       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package jdk.internal.dynalink;
+
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+
+/**
+ * Interface for objects that are used to transform one guarded invocation into another one. Typical usage is for
+ * implementing {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter) pre-link filters}.
+ */
+public interface GuardedInvocationFilter {
+    /**
+     * Given a guarded invocation, return a potentially different guarded invocation.
+     * @param inv the original guarded invocation. Null is never passed.
+     * @param linkRequest the link request for which the invocation was generated (usually by some linker).
+     * @param linkerServices the linker services that can be used during creation of a new invocation.
+     * @return either the passed guarded invocation or a different one, with the difference usually determined based on
+     * information in the link request and the differing invocation created with the assistance of the linker services.
+     * Whether or not {@code null} is an accepted return value is dependent on the user of the filter.
+     */
+    public GuardedInvocation filter(GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices);
+}
--- a/src/jdk/internal/dynalink/MonomorphicCallSite.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/MonomorphicCallSite.java	Thu Jun 05 19:38:45 2014 -0700
@@ -99,17 +99,17 @@
      * Creates a new call site with monomorphic inline caching strategy.
      * @param descriptor the descriptor for this call site
      */
-    public MonomorphicCallSite(CallSiteDescriptor descriptor) {
+    public MonomorphicCallSite(final CallSiteDescriptor descriptor) {
         super(descriptor);
     }
 
     @Override
-    public void relink(GuardedInvocation guardedInvocation, MethodHandle relink) {
+    public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
         setTarget(guardedInvocation.compose(relink));
     }
 
     @Override
-    public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relink) {
+    public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) {
         relink(guardedInvocation, relink);
     }
 }
--- a/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java	Thu Jun 05 19:38:45 2014 -0700
@@ -97,7 +97,7 @@
      * Creates a new NoSuchDynamicMethodException
      * @param message the message of the exception.
      */
-    public NoSuchDynamicMethodException(String message) {
+    public NoSuchDynamicMethodException(final String message) {
         super(message);
     }
 }
--- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -97,7 +97,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -107,6 +106,7 @@
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.internal.dynalink.support.Guards;
 import jdk.internal.dynalink.support.Lookup;
+import jdk.internal.dynalink.support.TypeUtilities;
 
 /**
  * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
@@ -123,18 +123,18 @@
     private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
     private final Map<String, DynamicMethod> methods = new HashMap<>();
 
-    AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) {
+    AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard) {
         this(clazz, classGuard, classGuard);
     }
 
-    AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard, MethodHandle assignableGuard) {
+    AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) {
         this.clazz = clazz;
         this.classGuard = classGuard;
         this.assignableGuard = assignableGuard;
 
         final FacetIntrospector introspector = createFacetIntrospector();
         // Add methods and properties
-        for(Method method: introspector.getMethods()) {
+        for(final Method method: introspector.getMethods()) {
             final String name = method.getName();
             // Add method
             addMember(name, method, methods);
@@ -153,7 +153,7 @@
         }
 
         // Add field getter/setters as property getters/setters.
-        for(Field field: introspector.getFields()) {
+        for(final Field field: introspector.getFields()) {
             final String name = field.getName();
             // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
             if(!propertyGetters.containsKey(name)) {
@@ -166,7 +166,7 @@
         }
 
         // Add inner classes, but only those for which we don't hide a property with it
-        for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
+        for(final Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
             final String name = innerClassSpec.getKey();
             if(!propertyGetters.containsKey(name)) {
                 setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
@@ -174,7 +174,7 @@
         }
     }
 
-    private static String decapitalize(String str) {
+    private static String decapitalize(final String str) {
         assert str != null;
         if(str.isEmpty()) {
             return str;
@@ -209,7 +209,7 @@
         return getUnmodifiableKeys(methods);
     }
 
-    private static Collection<String> getUnmodifiableKeys(Map<String, ?> m) {
+    private static Collection<String> getUnmodifiableKeys(final Map<String, ?> m) {
         return Collections.unmodifiableCollection(m.keySet());
     }
 
@@ -222,7 +222,7 @@
      * @param handle the method handle that implements the property getter
      * @param validationType the validation type for the property
      */
-    private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) {
+    private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) {
         propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
     }
 
@@ -232,7 +232,7 @@
      * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
      * names starting with "is".
      */
-    private void setPropertyGetter(Method getter, int prefixLen) {
+    private void setPropertyGetter(final Method getter, final int prefixLen) {
         setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
                 getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
     }
@@ -246,15 +246,15 @@
      * @param handle the method handle that implements the property getter
      * @param validationType the validation type for the property
      */
-    void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
+    void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) {
         setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
     }
 
-    private void addMember(String name, AccessibleObject ao, Map<String, DynamicMethod> methodMap) {
+    private void addMember(final String name, final AccessibleObject ao, final Map<String, DynamicMethod> methodMap) {
         addMember(name, createDynamicMethod(ao), methodMap);
     }
 
-    private void addMember(String name, SingleDynamicMethod method, Map<String, DynamicMethod> methodMap) {
+    private void addMember(final String name, final SingleDynamicMethod method, final Map<String, DynamicMethod> methodMap) {
         final DynamicMethod existingMethod = methodMap.get(name);
         final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
         if(newMethod != existingMethod) {
@@ -270,9 +270,9 @@
      * @param name the common name of the reflective members.
      * @return a dynamic method representing all the specified reflective members.
      */
-    static DynamicMethod createDynamicMethod(Iterable<? extends AccessibleObject> members, Class<?> clazz, String name) {
+    static DynamicMethod createDynamicMethod(final Iterable<? extends AccessibleObject> members, final Class<?> clazz, final String name) {
         DynamicMethod dynMethod = null;
-        for(AccessibleObject method: members) {
+        for(final AccessibleObject method: members) {
             dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
         }
         return dynMethod;
@@ -285,7 +285,7 @@
      * @param m the reflective member
      * @return the single dynamic method representing the reflective member
      */
-    private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) {
+    private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) {
         if(CallerSensitiveDetector.isCallerSensitive(m)) {
             return new CallerSensitiveDynamicMethod(m);
         }
@@ -301,7 +301,7 @@
      * @param m the method or constructor
      * @return the method handle
      */
-    private static MethodHandle unreflectSafely(AccessibleObject m) {
+    private static MethodHandle unreflectSafely(final AccessibleObject m) {
         if(m instanceof Method) {
             final Method reflMethod = (Method)m;
             final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod);
@@ -313,7 +313,7 @@
         return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor<?>)m));
     }
 
-    private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class<?> clazz, String name) {
+    private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class<?> clazz, final String name) {
         if(existing == null) {
             return method;
         } else if(existing.contains(method)) {
@@ -331,7 +331,7 @@
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
             throws Exception {
         final LinkRequest ncrequest = request.withoutRuntimeContext();
         // BeansLinker already checked that the name is at least 2 elements long and the first element is "dyn".
@@ -353,8 +353,8 @@
         return null;
     }
 
-    protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> operations) throws Exception {
+    protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> operations) throws Exception {
         if(operations.isEmpty()) {
             return null;
         }
@@ -374,27 +374,27 @@
         return null;
     }
 
-    static final <T> List<T> pop(List<T> l) {
+    static final <T> List<T> pop(final List<T> l) {
         return l.subList(1, l.size());
     }
 
-    MethodHandle getClassGuard(CallSiteDescriptor desc) {
+    MethodHandle getClassGuard(final CallSiteDescriptor desc) {
         return getClassGuard(desc.getMethodType());
     }
 
-    MethodHandle getClassGuard(MethodType type) {
+    MethodHandle getClassGuard(final MethodType type) {
         return Guards.asType(classGuard, type);
     }
 
-    GuardedInvocationComponent getClassGuardedInvocationComponent(MethodHandle invocation, MethodType type) {
+    GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) {
         return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
     }
 
-    private MethodHandle getAssignableGuard(MethodType type) {
+    private MethodHandle getAssignableGuard(final MethodType type) {
         return Guards.asType(assignableGuard, type);
     }
 
-    private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+    private GuardedInvocation getCallPropWithThis(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
         switch(callSiteDescriptor.getNameTokenCount()) {
             case 3: {
                 return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
@@ -406,25 +406,25 @@
         }
     }
 
-    private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){
+    private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap){
         final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
         return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
     }
 
-    private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap) {
+    private static MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap) {
         final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
         return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
     }
 
-    private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) {
+    private static DynamicMethod getDynamicMethod(final String methodName, final Map<String, DynamicMethod> methodMap) {
         final DynamicMethod dynaMethod = methodMap.get(methodName);
         return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
     }
 
-    private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName,
-            Map<String, DynamicMethod> methodsMap) {
+    private static SingleDynamicMethod getExplicitSignatureDynamicMethod(final String methodName,
+            final Map<String, DynamicMethod> methodsMap) {
         // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
         // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
         // resolution works correctly in almost every situation. However, in presence of many language-specific
@@ -457,14 +457,18 @@
     private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
             MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
 
-    private GuardedInvocationComponent getPropertySetter(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> operations) throws Exception {
-        final MethodType type = callSiteDescriptor.getMethodType();
+    private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> operations) throws Exception {
         switch(callSiteDescriptor.getNameTokenCount()) {
             case 2: {
                 // Must have three arguments: target object, property name, and property value.
                 assertParameterCount(callSiteDescriptor, 3);
 
+                // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
+                // valid for us to convert return values proactively. Also, since we don't know what setters will be
+                // invoked, we'll conservatively presume Object return type.
+                final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
+
                 // What's below is basically:
                 //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
                 //     get_setter_handle(type, linkerServices))
@@ -473,8 +477,8 @@
                 // component's invocation.
 
                 // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
-                // abbreviate to R(O, N, V) going forward.
-                // We want setters that conform to "R(O, V)"
+                // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
+                // Object return type).
                 final MethodType setterType = type.dropParameterTypes(1, 2);
                 // Bind property setter handle to the expected setter type and linker services. Type is
                 // MethodHandle(Object, String, Object)
@@ -495,11 +499,11 @@
 
                 final MethodHandle fallbackFolded;
                 if(nextComponent == null) {
-                    // Object(MethodHandle)->R(MethodHandle, O, N, V); returns constant null
+                    // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
                     fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
                             type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
                 } else {
-                    // R(O, N, V)->R(MethodHandle, O, N, V); adapts the next component's invocation to drop the
+                    // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
                     // extra argument resulting from fold
                     fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
                             0, MethodHandle.class);
@@ -543,11 +547,14 @@
             "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class));
     private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
 
-    private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> ops) throws Exception {
-        final MethodType type = callSiteDescriptor.getMethodType();
+    private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> ops) throws Exception {
         switch(callSiteDescriptor.getNameTokenCount()) {
             case 2: {
+                // Since we can't know what kind of a getter we'll get back on different invocations, we'll just
+                // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking
+                // runtime might not allow coercing at that call site.
+                final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
                 // Must have exactly two arguments: receiver and name
                 assertParameterCount(callSiteDescriptor, 2);
 
@@ -563,11 +570,11 @@
                         GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup());
                 final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
                         callSiteBoundMethodGetter);
-                // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0)
+                // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
                 final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
                         MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
                 // Since it's in the target of a fold, drop the unnecessary second argument
-                // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1)
+                // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1)
                 final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
                         type.parameterType(1));
                 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
@@ -575,17 +582,19 @@
 
                 final MethodHandle fallbackFolded;
                 if(nextComponent == null) {
-                    // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null
+                    // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null
                     fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
                             type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
                 } else {
-                    // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the
-                    // extra argument resulting from fold
-                    fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
-                            0, AnnotatedDynamicMethod.class);
+                    // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to
+                    // drop the extra argument resulting from fold and to change its return type to Object.
+                    final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation();
+                    final MethodType nextType = nextInvocation.type();
+                    fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType(
+                            nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class);
                 }
 
-                // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
+                // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
                 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
                             IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
                 if(nextComponent == null) {
@@ -612,8 +621,8 @@
                 // value is null.
                 final ValidationType validationType = annGetter.validationType;
                 // TODO: we aren't using the type that declares the most generic getter here!
-                return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType,
-                        type), clazz, validationType);
+                return new GuardedInvocationComponent(getter, getGuard(validationType,
+                        callSiteDescriptor.getMethodType()), clazz, validationType);
             }
             default: {
                 // Can't do anything with more than 3 name components
@@ -622,7 +631,7 @@
         }
     }
 
-    private MethodHandle getGuard(ValidationType validationType, MethodType methodType) {
+    private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) {
         switch(validationType) {
             case EXACT_CLASS: {
                 return getClassGuard(methodType);
@@ -642,21 +651,25 @@
         }
     }
 
-    private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
-            MethodType.methodType(boolean.class, DynamicMethod.class));
-    private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class);
+    private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class,
+            MethodType.methodType(boolean.class, Object.class));
+    private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class);
 
-    private GuardedInvocationComponent getMethodGetter(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> ops) throws Exception {
-        final MethodType type = callSiteDescriptor.getMethodType();
+    private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> ops) throws Exception {
+        // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to
+        // be visible outside of this linker, declare it to return Object.
+        final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
         switch(callSiteDescriptor.getNameTokenCount()) {
             case 2: {
                 // Must have exactly two arguments: receiver and name
                 assertParameterCount(callSiteDescriptor, 2);
                 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
                         linkerServices, ops);
-                if(nextComponent == null) {
-                    // No next component operation; just return a component for this operation.
+                if(nextComponent == null || !TypeUtilities.areAssignable(DynamicMethod.class,
+                        nextComponent.getGuardedInvocation().getInvocation().type().returnType())) {
+                    // No next component operation, or it can never produce a dynamic method; just return a component
+                    // for this operation.
                     return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
                 }
 
@@ -665,21 +678,20 @@
                 // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
                 // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
 
-                final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
-                        DynamicMethod.class));
+                final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type);
                 // Since it is part of the foldArgument() target, it will have extra args that we need to drop.
                 final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
-                        DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
-                                DynamicMethod.class));
+                        OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class));
                 final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
-                // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
-                assert nextComponentInvocation.type().equals(type);
+                // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the
+                // return type.
+                assert nextComponentInvocation.type().changeReturnType(type.returnType()).equals(type);
                 // Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
                 final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
-                        DynamicMethod.class);
+                        Object.class);
                 // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
                 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
-                        IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
+                        IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter);
 
                 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
             }
@@ -695,7 +707,7 @@
                 // No delegation to the next component of the composite operation; if we have a method with that name,
                 // we'll always return it at this point.
                 return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
-                        MethodHandles.constant(DynamicMethod.class, method), 0, type.parameterType(0)), type), type);
+                        MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
             }
             default: {
                 // Can't do anything with more than 3 name components
@@ -704,7 +716,31 @@
         }
     }
 
-    private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
+    static class MethodPair {
+        final MethodHandle method1;
+        final MethodHandle method2;
+
+        MethodPair(final MethodHandle method1, final MethodHandle method2) {
+            this.method1 = method1;
+            this.method2 = method2;
+        }
+
+        MethodHandle guardWithTest(final MethodHandle test) {
+            return MethodHandles.guardWithTest(test, method1, method2);
+        }
+    }
+
+    static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) {
+        final MethodType type1 = m1.type();
+        final MethodType type2 = m2.type();
+        final Class<?> commonRetType = TypeUtilities.getCommonLosslessConversionType(type1.returnType(),
+                type2.returnType());
+        return new MethodPair(
+                m1.asType(type1.changeReturnType(commonRetType)),
+                m2.asType(type2.changeReturnType(commonRetType)));
+    }
+
+    private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
         if(descriptor.getMethodType().parameterCount() != paramCount) {
             throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
         }
@@ -719,7 +755,7 @@
      * @return the method handle for retrieving the property, or null if the property does not exist
      */
     @SuppressWarnings("unused")
-    private Object getPropertyGetterHandle(Object id) {
+    private Object getPropertyGetterHandle(final Object id) {
         return propertyGetters.get(id);
     }
 
@@ -733,17 +769,20 @@
     private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
 
     @SuppressWarnings("unused")
-    private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices,
-            Object id) {
+    private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices,
+            final Object id) {
         return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
     }
 
     private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
-            "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class);
+            "getDynamicMethod", Object.class, Object.class), 1, Object.class);
     private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
 
     @SuppressWarnings("unused")
-    private DynamicMethod getDynamicMethod(Object name) {
+    // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't
+    // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for
+    // "dyn:getMethod" linking).
+    private Object getDynamicMethod(final Object name) {
         return getDynamicMethod(String.valueOf(name), methods);
     }
 
@@ -754,7 +793,7 @@
      * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
      * method with the specified name does not exist.
      */
-    DynamicMethod getDynamicMethod(String name) {
+    DynamicMethod getDynamicMethod(final String name) {
         return getDynamicMethod(name, methods);
     }
 
@@ -765,16 +804,16 @@
      * @param getter the getter
      * @return getter with same name, declared on the most generic superclass/interface of the declaring class
      */
-    private static Method getMostGenericGetter(Method getter) {
+    private static Method getMostGenericGetter(final Method getter) {
         return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
     }
 
-    private static Method getMostGenericGetter(String name, Class<?> returnType, Class<?> declaringClass) {
+    private static Method getMostGenericGetter(final String name, final Class<?> returnType, final Class<?> declaringClass) {
         if(declaringClass == null) {
             return null;
         }
         // Prefer interfaces
-        for(Class<?> itf: declaringClass.getInterfaces()) {
+        for(final Class<?> itf: declaringClass.getInterfaces()) {
             final Method itfGetter = getMostGenericGetter(name, returnType, itf);
             if(itfGetter != null) {
                 return itfGetter;
@@ -787,7 +826,7 @@
         if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
             try {
                 return declaringClass.getMethod(name);
-            } catch(NoSuchMethodException e) {
+            } catch(final NoSuchMethodException e) {
                 // Intentionally ignored, meant to fall through
             }
         }
@@ -798,18 +837,18 @@
         private final SingleDynamicMethod method;
         /*private*/ final ValidationType validationType;
 
-        AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) {
+        AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) {
             this.method = method;
             this.validationType = validationType;
         }
 
-        MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+        MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
             return method.getInvocation(callSiteDescriptor, linkerServices);
         }
 
         @SuppressWarnings("unused")
-        MethodHandle getTarget(MethodHandles.Lookup lookup) {
-            MethodHandle inv = method.getTarget(lookup);
+        MethodHandle getTarget(final MethodHandles.Lookup lookup) {
+            final MethodHandle inv = method.getTarget(lookup);
             assert inv != null;
             return inv;
         }
--- a/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java	Thu Jun 05 19:38:45 2014 -0700
@@ -104,7 +104,7 @@
 class AccessibleMembersLookup {
     private final Map<MethodSignature, Method> methods;
     private final Set<Class<?>> innerClasses;
-    private boolean instance;
+    private final boolean instance;
 
     /**
      * Creates a mapping for all accessible methods and inner classes on a class.
@@ -112,7 +112,7 @@
      * @param clazz the inspected class
      * @param instance true to inspect instance methods, false to inspect static methods.
      */
-    AccessibleMembersLookup(final Class<?> clazz, boolean instance) {
+    AccessibleMembersLookup(final Class<?> clazz, final boolean instance) {
         this.methods = new HashMap<>();
         this.innerClasses = new LinkedHashSet<>();
         this.instance = instance;
@@ -153,7 +153,7 @@
          * @param name the name of the method this signature represents.
          * @param args the argument types of the method.
          */
-        MethodSignature(String name, Class<?>[] args) {
+        MethodSignature(final String name, final Class<?>[] args) {
             this.name = name;
             this.args = args;
         }
@@ -210,7 +210,7 @@
 
         if(!CheckRestrictedPackage.isRestrictedClass(clazz)) {
             searchSuperTypes = false;
-            for(Method method: clazz.getMethods()) {
+            for(final Method method: clazz.getMethods()) {
                 final boolean isStatic = Modifier.isStatic(method.getModifiers());
                 if(instance != isStatic) {
                     final MethodSignature sig = new MethodSignature(method);
@@ -237,7 +237,7 @@
                     }
                 }
             }
-            for(Class<?> innerClass: clazz.getClasses()) {
+            for(final Class<?> innerClass: clazz.getClasses()) {
                 // Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just
                 // expose non-static classes with explicit constructor outer class argument.
                 // NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes
--- a/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java	Thu Jun 05 19:38:45 2014 -0700
@@ -108,7 +108,7 @@
     ApplicableOverloadedMethods(final List<SingleDynamicMethod> methods, final MethodType callSiteType,
             final ApplicabilityTest test) {
         this.methods = new LinkedList<>();
-        for(SingleDynamicMethod m: methods) {
+        for(final SingleDynamicMethod m: methods) {
             if(test.isApplicable(callSiteType, m)) {
                 this.methods.add(m);
             }
@@ -143,7 +143,7 @@
      */
     static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() {
         @Override
-        boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
             final MethodType methodType = method.getMethodType();
             final int methodArity = methodType.parameterCount();
             if(methodArity != callSiteType.parameterCount()) {
@@ -165,7 +165,7 @@
      */
     static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() {
         @Override
-        boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
             final MethodType methodType = method.getMethodType();
             final int methodArity = methodType.parameterCount();
             if(methodArity != callSiteType.parameterCount()) {
@@ -188,7 +188,7 @@
      */
     static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() {
         @Override
-        boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) {
+        boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) {
             if(!method.isVarArgs()) {
                 return false;
             }
--- a/src/jdk/internal/dynalink/beans/BeanIntrospector.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/BeanIntrospector.java	Thu Jun 05 19:38:45 2014 -0700
@@ -88,7 +88,7 @@
 import java.util.Map;
 
 class BeanIntrospector extends FacetIntrospector {
-    BeanIntrospector(Class<?> clazz) {
+    BeanIntrospector(final Class<?> clazz) {
         super(clazz, true);
     }
 
@@ -98,7 +98,7 @@
     }
 
     @Override
-    MethodHandle editMethodHandle(MethodHandle mh) {
+    MethodHandle editMethodHandle(final MethodHandle mh) {
         return mh;
     }
 }
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/BeanLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -106,7 +106,7 @@
  * @author Attila Szegedi
  */
 class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker {
-    BeanLinker(Class<?> clazz) {
+    BeanLinker(final Class<?> clazz) {
         super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz));
         if(clazz.isArray()) {
             // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an
@@ -119,7 +119,7 @@
     }
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return type == clazz;
     }
 
@@ -129,8 +129,8 @@
     }
 
     @Override
-    protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> operations) throws Exception {
+    protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> operations) throws Exception {
         final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor,
                 linkerServices, operations);
         if(superGic != null) {
@@ -166,7 +166,7 @@
     private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
 
     private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, List<String> operations) throws Exception {
+            final LinkerServices linkerServices, final List<String> operations) throws Exception {
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
         final Class<?> declaredType = callSiteType.parameterType(0);
         final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
@@ -237,8 +237,9 @@
         } else {
             checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
         }
-        return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
-                binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
+        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+                nextComponent.getGuardedInvocation().getInvocation());
+        return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
                 gic.getValidatorClass(), gic.getValidationType());
     }
 
@@ -247,7 +248,7 @@
                 CallSiteDescriptor.NAME_OPERAND);
     }
 
-    private static Object convertKeyToInteger(String fixedKey, LinkerServices linkerServices) throws Exception {
+    private static Object convertKeyToInteger(final String fixedKey, final LinkerServices linkerServices) throws Exception {
         try {
             if(linkerServices.canConvert(String.class, Number.class)) {
                 try {
@@ -267,18 +268,18 @@
                     return Integer.valueOf(intIndex);
                 } catch(Exception|Error e) {
                     throw e;
-                } catch(Throwable t) {
+                } catch(final Throwable t) {
                     throw new RuntimeException(t);
                 }
             }
             return Integer.valueOf(fixedKey);
-        } catch(NumberFormatException e) {
+        } catch(final NumberFormatException e) {
             // key is not a number
             return null;
         }
     }
 
-    private static MethodHandle convertArgToInt(MethodHandle mh, LinkerServices ls, CallSiteDescriptor desc) {
+    private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) {
         final Class<?> sourceType = desc.getMethodType().parameterType(1);
         if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) {
             return mh;
@@ -301,21 +302,21 @@
         private final MethodType methodType;
         private final Object fixedKey;
 
-        Binder(LinkerServices linkerServices, MethodType methodType, Object fixedKey) {
+        Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) {
             this.linkerServices = linkerServices;
             this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass());
             this.fixedKey = fixedKey;
         }
 
-        /*private*/ MethodHandle bind(MethodHandle handle) {
-            return bindToFixedKey(linkerServices.asType(handle, methodType));
+        /*private*/ MethodHandle bind(final MethodHandle handle) {
+            return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType));
         }
 
-        /*private*/ MethodHandle bindTest(MethodHandle handle) {
+        /*private*/ MethodHandle bindTest(final MethodHandle handle) {
             return bindToFixedKey(Guards.asType(handle, methodType));
         }
 
-        private MethodHandle bindToFixedKey(MethodHandle handle) {
+        private MethodHandle bindToFixedKey(final MethodHandle handle) {
             return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey);
         }
     }
@@ -325,12 +326,12 @@
     private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
             MethodType.methodType(boolean.class, Object.class));
 
-    private static MethodHandle findRangeCheck(Class<?> collectionType) {
+    private static MethodHandle findRangeCheck(final Class<?> collectionType) {
         return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class);
     }
 
     @SuppressWarnings("unused")
-    private static final boolean rangeCheck(Object array, Object index) {
+    private static final boolean rangeCheck(final Object array, final Object index) {
         if(!(index instanceof Number)) {
             return false;
         }
@@ -347,7 +348,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static final boolean rangeCheck(List<?> list, Object index) {
+    private static final boolean rangeCheck(final List<?> list, final Object index) {
         if(!(index instanceof Number)) {
             return false;
         }
@@ -369,8 +370,8 @@
     private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
             MethodType.methodType(Object.class, Object.class, Object.class));
 
-    private GuardedInvocationComponent getElementSetter(CallSiteDescriptor callSiteDescriptor,
-            LinkerServices linkerServices, List<String> operations) throws Exception {
+    private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor,
+            final LinkerServices linkerServices, final List<String> operations) throws Exception {
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
         final Class<?> declaredType = callSiteType.parameterType(0);
 
@@ -440,8 +441,9 @@
 
         final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
             RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
-        return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
-                binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
+        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+                nextComponent.getGuardedInvocation().getInvocation());
+        return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
                 gic.getValidatorClass(), gic.getValidationType());
     }
 
@@ -456,7 +458,7 @@
 
     private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
 
-    private GuardedInvocationComponent getLengthGetter(CallSiteDescriptor callSiteDescriptor) {
+    private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) {
         assertParameterCount(callSiteDescriptor, 1);
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
         final Class<?> declaredType = callSiteType.parameterType(0);
@@ -486,7 +488,7 @@
         return null;
     }
 
-    private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
+    private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
         if(descriptor.getMethodType().parameterCount() != paramCount) {
             throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
         }
--- a/src/jdk/internal/dynalink/beans/BeansLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/BeansLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -131,7 +131,7 @@
 public class BeansLinker implements GuardingDynamicLinker {
     private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
         @Override
-        protected TypeBasedGuardingDynamicLinker computeValue(Class<?> clazz) {
+        protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) {
             // If ClassValue.put() were public, we could just pre-populate with these known mappings...
             return
                 clazz == Class.class ? new ClassLinker() :
@@ -154,7 +154,7 @@
      * @param clazz the class
      * @return a bean linker for that class
      */
-    public static TypeBasedGuardingDynamicLinker getLinkerForClass(Class<?> clazz) {
+    public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) {
         return linkers.get(clazz);
     }
 
@@ -173,8 +173,8 @@
      * @param clazz the class
      * @return a collection of names of all readable instance properties of a class.
      */
-    public static Collection<String> getReadableInstancePropertyNames(Class<?> clazz) {
-        TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+    public static Collection<String> getReadableInstancePropertyNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
         if(linker instanceof BeanLinker) {
             return ((BeanLinker)linker).getReadablePropertyNames();
         }
@@ -186,8 +186,8 @@
      * @param clazz the class
      * @return a collection of names of all writable instance properties of a class.
      */
-    public static Collection<String> getWritableInstancePropertyNames(Class<?> clazz) {
-        TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+    public static Collection<String> getWritableInstancePropertyNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
         if(linker instanceof BeanLinker) {
             return ((BeanLinker)linker).getWritablePropertyNames();
         }
@@ -199,8 +199,8 @@
      * @param clazz the class
      * @return a collection of names of all instance methods of a class.
      */
-    public static Collection<String> getInstanceMethodNames(Class<?> clazz) {
-        TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
+    public static Collection<String> getInstanceMethodNames(final Class<?> clazz) {
+        final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz);
         if(linker instanceof BeanLinker) {
             return ((BeanLinker)linker).getMethodNames();
         }
@@ -212,7 +212,7 @@
      * @param clazz the class
      * @return a collection of names of all readable static properties of a class.
      */
-    public static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) {
+    public static Collection<String> getReadableStaticPropertyNames(final Class<?> clazz) {
         return StaticClassLinker.getReadableStaticPropertyNames(clazz);
     }
 
@@ -221,7 +221,7 @@
      * @param clazz the class
      * @return a collection of names of all writable static properties of a class.
      */
-    public static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) {
+    public static Collection<String> getWritableStaticPropertyNames(final Class<?> clazz) {
         return StaticClassLinker.getWritableStaticPropertyNames(clazz);
     }
 
@@ -230,12 +230,12 @@
      * @param clazz the class
      * @return a collection of names of all static methods of a class.
      */
-    public static Collection<String> getStaticMethodNames(Class<?> clazz) {
+    public static Collection<String> getStaticMethodNames(final Class<?> clazz) {
         return StaticClassLinker.getStaticMethodNames(clazz);
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
             throws Exception {
         final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
         final int l = callSiteDescriptor.getNameTokenCount();
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java	Thu Jun 05 19:38:45 2014 -0700
@@ -107,14 +107,14 @@
 
     private static final DetectionStrategy DETECTION_STRATEGY = getDetectionStrategy();
 
-    static boolean isCallerSensitive(AccessibleObject ao) {
+    static boolean isCallerSensitive(final AccessibleObject ao) {
         return DETECTION_STRATEGY.isCallerSensitive(ao);
     }
 
     private static DetectionStrategy getDetectionStrategy() {
         try {
             return new PrivilegedDetectionStrategy();
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             return new UnprivilegedDetectionStrategy();
         }
     }
@@ -127,7 +127,7 @@
         private static final Class<? extends Annotation> CALLER_SENSITIVE_ANNOTATION_CLASS = CallerSensitive.class;
 
         @Override
-        boolean isCallerSensitive(AccessibleObject ao) {
+        boolean isCallerSensitive(final AccessibleObject ao) {
             return ao.getAnnotation(CALLER_SENSITIVE_ANNOTATION_CLASS) != null;
         }
     }
@@ -136,8 +136,8 @@
         private static final String CALLER_SENSITIVE_ANNOTATION_STRING = "@sun.reflect.CallerSensitive()";
 
         @Override
-        boolean isCallerSensitive(AccessibleObject o) {
-            for(Annotation a: o.getAnnotations()) {
+        boolean isCallerSensitive(final AccessibleObject o) {
+            for(final Annotation a: o.getAnnotations()) {
                 if(String.valueOf(a).equals(CALLER_SENSITIVE_ANNOTATION_STRING)) {
                     return true;
                 }
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -107,13 +107,13 @@
     private final AccessibleObject target;
     private final MethodType type;
 
-    public CallerSensitiveDynamicMethod(AccessibleObject target) {
+    public CallerSensitiveDynamicMethod(final AccessibleObject target) {
         super(getName(target));
         this.target = target;
         this.type = getMethodType(target);
     }
 
-    private static String getName(AccessibleObject target) {
+    private static String getName(final AccessibleObject target) {
         final Member m = (Member)target;
         return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
                 m.getName()));
@@ -124,7 +124,7 @@
         return type;
     }
 
-    private static MethodType getMethodType(AccessibleObject ao) {
+    private static MethodType getMethodType(final AccessibleObject ao) {
         final boolean isMethod = ao instanceof Method;
         final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass();
         final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes();
@@ -144,7 +144,7 @@
     }
 
     @Override
-    MethodHandle getTarget(MethodHandles.Lookup lookup) {
+    MethodHandle getTarget(final MethodHandles.Lookup lookup) {
         if(target instanceof Method) {
             final MethodHandle mh = Lookup.unreflect(lookup, (Method)target);
             if(Modifier.isStatic(((Member)target).getModifiers())) {
--- a/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java	Thu Jun 05 19:38:45 2014 -0700
@@ -101,7 +101,7 @@
      * @param clazz the class to test
      * @return true if the class is either not public, or it resides in a package with restricted access.
      */
-    static boolean isRestrictedClass(Class<?> clazz) {
+    static boolean isRestrictedClass(final Class<?> clazz) {
         if(!Modifier.isPublic(clazz.getModifiers())) {
             // Non-public classes are always restricted
             return true;
@@ -126,7 +126,7 @@
                     return null;
                 }
             }, NO_PERMISSIONS_CONTEXT);
-        } catch(SecurityException e) {
+        } catch(final SecurityException e) {
             return true;
         }
         return false;
--- a/src/jdk/internal/dynalink/beans/ClassString.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/ClassString.java	Thu Jun 05 19:38:45 2014 -0700
@@ -104,16 +104,16 @@
     private final Class<?>[] classes;
     private int hashCode;
 
-    ClassString(Class<?>[] classes) {
+    ClassString(final Class<?>[] classes) {
         this.classes = classes;
     }
 
-    ClassString(MethodType type) {
+    ClassString(final MethodType type) {
         this(type.parameterArray());
     }
 
     @Override
-    public boolean equals(Object other) {
+    public boolean equals(final Object other) {
         if(!(other instanceof ClassString)) {
             return false;
         }
@@ -150,7 +150,7 @@
         return true;
     }
 
-    List<MethodHandle> getMaximallySpecifics(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
+    List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
         return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg),
                 varArg, classes, linkerServices);
     }
@@ -158,7 +158,7 @@
     /**
      * Returns all methods that are applicable to actual parameter classes represented by this ClassString object.
      */
-    LinkedList<MethodHandle> getApplicables(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
+    LinkedList<MethodHandle> getApplicables(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
         final LinkedList<MethodHandle> list = new LinkedList<>();
         for(final MethodHandle member: methods) {
             if(isApplicable(member, linkerServices, varArg)) {
@@ -173,7 +173,7 @@
      * object.
      *
      */
-    private boolean isApplicable(MethodHandle method, LinkerServices linkerServices, boolean varArg) {
+    private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) {
         final Class<?>[] formalTypes = method.type().parameterArray();
         final int cl = classes.length;
         final int fl = formalTypes.length - (varArg ? 1 : 0);
@@ -203,7 +203,7 @@
         return true;
     }
 
-    private static boolean canConvert(LinkerServices ls, Class<?> from, Class<?> to) {
+    private static boolean canConvert(final LinkerServices ls, final Class<?> from, final Class<?> to) {
         if(from == NULL_CLASS) {
             return !to.isPrimitive();
         }
--- a/src/jdk/internal/dynalink/beans/DynamicMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/DynamicMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -99,7 +99,7 @@
 abstract class DynamicMethod {
     private final String name;
 
-    DynamicMethod(String name) {
+    DynamicMethod(final String name) {
         this.name = name;
     }
 
@@ -138,7 +138,7 @@
      */
     abstract boolean contains(SingleDynamicMethod method);
 
-    static String getClassAndMethodName(Class<?> clazz, String name) {
+    static String getClassAndMethodName(final Class<?> clazz, final String name) {
         final String clazzName = clazz.getCanonicalName();
         return (clazzName == null ? clazz.getName() : clazzName) + "." + name;
     }
--- a/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -99,12 +99,12 @@
  */
 class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return DynamicMethod.class.isAssignableFrom(type);
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) {
         final Object receiver = linkRequest.getReceiver();
         if(!(receiver instanceof DynamicMethod)) {
             return null;
--- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java	Thu Jun 05 19:38:45 2014 -0700
@@ -106,7 +106,7 @@
 
     protected final AccessibleMembersLookup membersLookup;
 
-    FacetIntrospector(Class<?> clazz, boolean instance) {
+    FacetIntrospector(final Class<?> clazz, final boolean instance) {
         this.clazz = clazz;
         this.instance = instance;
         isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz);
@@ -135,7 +135,7 @@
 
         final Field[] fields = clazz.getFields();
         final Collection<Field> cfields = new ArrayList<>(fields.length);
-        for(Field field: fields) {
+        for(final Field field: fields) {
             final boolean isStatic = Modifier.isStatic(field.getModifiers());
             if(isStatic && clazz != field.getDeclaringClass()) {
                 // ignore inherited static fields
@@ -149,7 +149,7 @@
         return cfields;
     }
 
-    boolean isAccessible(Member m) {
+    boolean isAccessible(final Member m) {
         final Class<?> declaring = m.getDeclaringClass();
         // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a
         // non-restriced class, so if the declaring class is identical to the class being inspected, then forego
@@ -166,11 +166,11 @@
     }
 
 
-    MethodHandle unreflectGetter(Field field) {
+    MethodHandle unreflectGetter(final Field field) {
         return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field));
     }
 
-    MethodHandle unreflectSetter(Field field) {
+    MethodHandle unreflectSetter(final Field field) {
         return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field));
     }
 
--- a/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java	Thu Jun 05 19:38:45 2014 -0700
@@ -105,38 +105,38 @@
     private final GuardedInvocation guardedInvocation;
     private final Validator validator;
 
-    GuardedInvocationComponent(MethodHandle invocation) {
+    GuardedInvocationComponent(final MethodHandle invocation) {
         this(invocation, null, ValidationType.NONE);
     }
 
-    GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, ValidationType validationType) {
+    GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) {
         this(invocation, guard, null, validationType);
     }
 
-    GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Class<?> validatorClass,
-            ValidationType validationType) {
+    GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
+            final ValidationType validationType) {
         this(invocation, guard, new Validator(validatorClass, validationType));
     }
 
-    GuardedInvocationComponent(GuardedInvocation guardedInvocation, Class<?> validatorClass,
-            ValidationType validationType) {
+    GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class<?> validatorClass,
+            final ValidationType validationType) {
         this(guardedInvocation, new Validator(validatorClass, validationType));
     }
 
-    GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation) {
+    GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) {
         return replaceInvocation(newInvocation, guardedInvocation.getGuard());
     }
 
-    GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation, MethodHandle newGuard) {
+    GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) {
         return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation,
                 newGuard), validator);
     }
 
-    private GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Validator validator) {
+    private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) {
         this(new GuardedInvocation(invocation, guard), validator);
     }
 
-    private GuardedInvocationComponent(GuardedInvocation guardedInvocation, Validator validator) {
+    private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) {
         this.guardedInvocation = guardedInvocation;
         this.validator = validator;
     }
@@ -153,8 +153,8 @@
         return validator.validationType;
     }
 
-    GuardedInvocationComponent compose(MethodHandle compositeInvocation, MethodHandle otherGuard,
-            Class<?> otherValidatorClass, ValidationType otherValidationType) {
+    GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard,
+            final Class<?> otherValidatorClass, final ValidationType otherValidationType) {
         final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType));
         final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard;
         return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator);
@@ -164,12 +164,12 @@
         /*private*/ final Class<?> validatorClass;
         /*private*/ final ValidationType validationType;
 
-        Validator(Class<?> validatorClass, ValidationType validationType) {
+        Validator(final Class<?> validatorClass, final ValidationType validationType) {
             this.validatorClass = validatorClass;
             this.validationType = validationType;
         }
 
-        Validator compose(Validator other) {
+        Validator compose(final Validator other) {
             if(other.validationType == ValidationType.NONE) {
                 return this;
             }
@@ -240,7 +240,7 @@
             throw new AssertionError("Incompatible composition " + this + " vs " + other);
         }
 
-        private boolean isAssignableFrom(Validator other) {
+        private boolean isAssignableFrom(final Validator other) {
             return validatorClass.isAssignableFrom(other.validatorClass);
         }
 
--- a/src/jdk/internal/dynalink/beans/MaximallySpecific.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/MaximallySpecific.java	Thu Jun 05 19:38:45 2014 -0700
@@ -105,7 +105,7 @@
      * @param varArgs whether to assume the methods are varargs
      * @return the list of maximally specific methods.
      */
-    static List<SingleDynamicMethod> getMaximallySpecificMethods(List<SingleDynamicMethod> methods, boolean varArgs) {
+    static List<SingleDynamicMethod> getMaximallySpecificMethods(final List<SingleDynamicMethod> methods, final boolean varArgs) {
         return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null);
     }
 
@@ -116,7 +116,7 @@
     private static final MethodTypeGetter<MethodHandle> METHOD_HANDLE_TYPE_GETTER =
             new MethodTypeGetter<MethodHandle>() {
         @Override
-        MethodType getMethodType(MethodHandle t) {
+        MethodType getMethodType(final MethodHandle t) {
             return t.type();
         }
     };
@@ -124,7 +124,7 @@
     private static final MethodTypeGetter<SingleDynamicMethod> DYNAMIC_METHOD_TYPE_GETTER =
             new MethodTypeGetter<SingleDynamicMethod>() {
         @Override
-        MethodType getMethodType(SingleDynamicMethod t) {
+        MethodType getMethodType(final SingleDynamicMethod t) {
             return t.getMethodType();
         }
     };
@@ -138,8 +138,8 @@
       * @param argTypes concrete argument types for the invocation
       * @return the list of maximally specific method handles.
       */
-     static List<MethodHandle> getMaximallySpecificMethodHandles(List<MethodHandle> methods, boolean varArgs,
-             Class<?>[] argTypes, LinkerServices ls) {
+     static List<MethodHandle> getMaximallySpecificMethodHandles(final List<MethodHandle> methods, final boolean varArgs,
+             final Class<?>[] argTypes, final LinkerServices ls) {
          return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER);
      }
 
@@ -152,8 +152,8 @@
       * @param argTypes concrete argument types for the invocation
       * @return the list of maximally specific methods.
       */
-     static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(List<SingleDynamicMethod> methods,
-             boolean varArgs, Class<?>[] argTypes, LinkerServices ls) {
+     static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(final List<SingleDynamicMethod> methods,
+             final boolean varArgs, final Class<?>[] argTypes, final LinkerServices ls) {
          return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER);
      }
 
@@ -166,16 +166,16 @@
      * @param argTypes concrete argument types for the invocation
      * @return the list of maximally specific methods.
      */
-    private static <T> List<T> getMaximallySpecificMethods(List<T> methods, boolean varArgs,
-            Class<?>[] argTypes, LinkerServices ls, MethodTypeGetter<T> methodTypeGetter) {
+    private static <T> List<T> getMaximallySpecificMethods(final List<T> methods, final boolean varArgs,
+            final Class<?>[] argTypes, final LinkerServices ls, final MethodTypeGetter<T> methodTypeGetter) {
         if(methods.size() < 2) {
             return methods;
         }
         final LinkedList<T> maximals = new LinkedList<>();
-        for(T m: methods) {
+        for(final T m: methods) {
             final MethodType methodType = methodTypeGetter.getMethodType(m);
             boolean lessSpecific = false;
-            for(Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) {
+            for(final Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) {
                 final T max = maximal.next();
                 switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) {
                     case TYPE_1_BETTER: {
@@ -202,8 +202,8 @@
         return maximals;
     }
 
-    private static Comparison isMoreSpecific(MethodType t1, MethodType t2, boolean varArgs, Class<?>[] argTypes,
-            LinkerServices ls) {
+    private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class<?>[] argTypes,
+            final LinkerServices ls) {
         final int pc1 = t1.parameterCount();
         final int pc2 = t2.parameterCount();
         assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1);
@@ -241,7 +241,7 @@
         return Comparison.INDETERMINATE;
     }
 
-    private static Comparison compare(Class<?> c1, Class<?> c2, Class<?>[] argTypes, int i, LinkerServices cmp) {
+    private static Comparison compare(final Class<?> c1, final Class<?> c2, final Class<?>[] argTypes, final int i, final LinkerServices cmp) {
         if(cmp != null) {
             final Comparison c = cmp.compareConversion(argTypes[i], c1, c2);
             if(c != Comparison.INDETERMINATE) {
@@ -256,7 +256,7 @@
         return Comparison.INDETERMINATE;
     }
 
-    private static Class<?> getParameterClass(MethodType t, int l, int i, boolean varArgs) {
+    private static Class<?> getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) {
         return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i);
     }
 }
--- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -115,20 +115,20 @@
      * @param clazz the class this method belongs to
      * @param name the name of the method
      */
-    OverloadedDynamicMethod(Class<?> clazz, String name) {
+    OverloadedDynamicMethod(final Class<?> clazz, final String name) {
         this(new LinkedList<SingleDynamicMethod>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name));
     }
 
-    private OverloadedDynamicMethod(LinkedList<SingleDynamicMethod> methods, ClassLoader classLoader, String name) {
+    private OverloadedDynamicMethod(final LinkedList<SingleDynamicMethod> methods, final ClassLoader classLoader, final String name) {
         super(name);
         this.methods = methods;
         this.classLoader = classLoader;
     }
 
     @Override
-    SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
+    SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) {
         final LinkedList<SingleDynamicMethod> matchingMethods = new LinkedList<>();
-        for(SingleDynamicMethod method: methods) {
+        for(final SingleDynamicMethod method: methods) {
             final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes);
             if(matchingMethod != null) {
                 matchingMethods.add(matchingMethod);
@@ -148,7 +148,6 @@
         }
     }
 
-    @SuppressWarnings("fallthrough")
     @Override
     public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
@@ -207,7 +206,7 @@
             case 1: {
                 // Very lucky, we ended up with a single candidate method handle based on the call site signature; we
                 // can link it very simply by delegating to the SingleDynamicMethod.
-                invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices);
+                return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices);
             }
             default: {
                 // We have more than one candidate. We have no choice but to link to a method that resolves overloads on
@@ -218,7 +217,7 @@
                 // has an already determined Lookup.
                 final List<MethodHandle> methodHandles = new ArrayList<>(invokables.size());
                 final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup();
-                for(SingleDynamicMethod method: invokables) {
+                for(final SingleDynamicMethod method: invokables) {
                     methodHandles.add(method.getTarget(lookup));
                 }
                 return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker();
@@ -228,8 +227,8 @@
     }
 
     @Override
-    public boolean contains(SingleDynamicMethod m) {
-        for(SingleDynamicMethod method: methods) {
+    public boolean contains(final SingleDynamicMethod m) {
+        for(final SingleDynamicMethod method: methods) {
             if(method.contains(m)) {
                 return true;
             }
@@ -241,8 +240,8 @@
         return classLoader;
     }
 
-    private static boolean isApplicableDynamically(LinkerServices linkerServices, MethodType callSiteType,
-            SingleDynamicMethod m) {
+    private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType,
+            final SingleDynamicMethod m) {
         final MethodType methodType = m.getMethodType();
         final boolean varArgs = m.isVarArgs();
         final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
@@ -288,13 +287,13 @@
         return true;
     }
 
-    private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType,
-            Class<?> methodType) {
+    private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class<?> callSiteType,
+            final Class<?> methodType) {
         return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType)
                 || linkerServices.canConvert(callSiteType, methodType);
     }
 
-    private ApplicableOverloadedMethods getApplicables(MethodType callSiteType, ApplicabilityTest test) {
+    private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) {
         return new ApplicableOverloadedMethods(methods, callSiteType, test);
     }
 
@@ -303,7 +302,7 @@
      *
      * @param method a method to add
      */
-    public void addMethod(SingleDynamicMethod method) {
+    public void addMethod(final SingleDynamicMethod method) {
         methods.add(method);
     }
 }
--- a/src/jdk/internal/dynalink/beans/OverloadedMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/OverloadedMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -93,6 +93,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.support.Lookup;
+import jdk.internal.dynalink.support.TypeUtilities;
 
 /**
  * Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or
@@ -111,16 +112,18 @@
     private final ArrayList<MethodHandle> fixArgMethods;
     private final ArrayList<MethodHandle> varArgMethods;
 
-    OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
-            LinkerServices linkerServices) {
+    OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
+            final LinkerServices linkerServices) {
         this.parent = parent;
-        this.callSiteType = callSiteType;
+        final Class<?> commonRetType = getCommonReturnType(methodHandles);
+        this.callSiteType = callSiteType.changeReturnType(commonRetType);
         this.linkerServices = linkerServices;
 
         fixArgMethods = new ArrayList<>(methodHandles.size());
         varArgMethods = new ArrayList<>(methodHandles.size());
         final int argNum = callSiteType.parameterCount();
         for(MethodHandle mh: methodHandles) {
+            mh = mh.asType(mh.type().changeReturnType(commonRetType));
             if(mh.isVarargsCollector()) {
                 final MethodHandle asFixed = mh.asFixedArity();
                 if(argNum == asFixed.type().parameterCount()) {
@@ -137,7 +140,7 @@
         final MethodHandle bound = SELECT_METHOD.bindTo(this);
         final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
                 callSiteType.changeReturnType(MethodHandle.class));
-        invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
+        invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(this.callSiteType), collecting);
     }
 
     MethodHandle getInvoker() {
@@ -148,7 +151,7 @@
             MethodHandle.class, Object[].class);
 
     @SuppressWarnings("unused")
-    private MethodHandle selectMethod(Object[] args) throws NoSuchMethodException {
+    private MethodHandle selectMethod(final Object[] args) throws NoSuchMethodException {
         final Class<?>[] argTypes = new Class[args.length];
         for(int i = 0; i < argTypes.length; ++i) {
             final Object arg = args[i];
@@ -185,7 +188,7 @@
         return method;
     }
 
-    private MethodHandle getNoSuchMethodThrower(Class<?>[] argTypes) {
+    private MethodHandle getNoSuchMethodThrower(final Class<?>[] argTypes) {
         return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes));
     }
 
@@ -193,7 +196,7 @@
             "throwNoSuchMethod", void.class, Class[].class);
 
     @SuppressWarnings("unused")
-    private void throwNoSuchMethod(Class<?>[] argTypes) throws NoSuchMethodException {
+    private void throwNoSuchMethod(final Class<?>[] argTypes) throws NoSuchMethodException {
         if(varArgMethods.isEmpty()) {
             throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) +
                     " of method " + parent.getName() + " match the argument types " + argTypesString(argTypes));
@@ -203,11 +206,11 @@
                 parent.getName() + " match the argument types " + argTypesString(argTypes));
     }
 
-    private MethodHandle getAmbiguousMethodThrower(Class<?>[] argTypes, List<MethodHandle> methods) {
+    private MethodHandle getAmbiguousMethodThrower(final Class<?>[] argTypes, final List<MethodHandle> methods) {
         return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods));
     }
 
-    private MethodHandle adaptThrower(MethodHandle rawThrower) {
+    private MethodHandle adaptThrower(final MethodHandle rawThrower) {
         return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType);
     }
 
@@ -215,20 +218,20 @@
             "throwAmbiguousMethod", void.class, Class[].class, List.class);
 
     @SuppressWarnings("unused")
-    private void throwAmbiguousMethod(Class<?>[] argTypes, List<MethodHandle> methods) throws NoSuchMethodException {
+    private void throwAmbiguousMethod(final Class<?>[] argTypes, final List<MethodHandle> methods) throws NoSuchMethodException {
         final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed";
         throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " +
                 getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " +
                 argTypesString(argTypes));
     }
 
-    private static String argTypesString(Class<?>[] classes) {
+    private static String argTypesString(final Class<?>[] classes) {
         final StringBuilder b = new StringBuilder().append('[');
         appendTypes(b, classes, false);
         return b.append(']').toString();
     }
 
-    private static String getSignatureList(List<MethodHandle> methods) {
+    private static String getSignatureList(final List<MethodHandle> methods) {
         final StringBuilder b = new StringBuilder().append('[');
         final Iterator<MethodHandle> it = methods.iterator();
         if(it.hasNext()) {
@@ -240,13 +243,13 @@
         return b.append(']').toString();
     }
 
-    private static void appendSig(StringBuilder b, MethodHandle m) {
+    private static void appendSig(final StringBuilder b, final MethodHandle m) {
         b.append('(');
         appendTypes(b, m.type().parameterArray(), m.isVarargsCollector());
         b.append(')');
     }
 
-    private static void appendTypes(StringBuilder b, Class<?>[] classes, boolean varArg) {
+    private static void appendTypes(final StringBuilder b, final Class<?>[] classes, final boolean varArg) {
         final int l = classes.length;
         if(!varArg) {
             if(l > 1) {
@@ -262,4 +265,13 @@
             b.append(classes[l - 1].getComponentType().getCanonicalName()).append("...");
         }
     }
+
+    private static Class<?> getCommonReturnType(final List<MethodHandle> methodHandles) {
+        final Iterator<MethodHandle> it = methodHandles.iterator();
+        Class<?> retType = it.next().type().returnType();
+        while(it.hasNext()) {
+            retType = TypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType());
+        }
+        return retType;
+    }
 }
--- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -107,12 +107,12 @@
      * @param clazz the class declaring the method
      * @param name the simple name of the method
      */
-    SimpleDynamicMethod(MethodHandle target, Class<?> clazz, String name) {
+    SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name) {
         super(getName(target, clazz, name));
         this.target = target;
     }
 
-    private static String getName(MethodHandle target, Class<?> clazz, String name) {
+    private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
         return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
     }
 
@@ -127,7 +127,7 @@
     }
 
     @Override
-    MethodHandle getTarget(Lookup lookup) {
+    MethodHandle getTarget(final Lookup lookup) {
         return target;
     }
 }
--- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Thu Jun 05 19:38:45 2014 -0700
@@ -104,7 +104,7 @@
 
     private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class);
 
-    SingleDynamicMethod(String name) {
+    SingleDynamicMethod(final String name) {
         super(name);
     }
 
@@ -128,22 +128,22 @@
     abstract MethodHandle getTarget(MethodHandles.Lookup lookup);
 
     @Override
-    MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
+    MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
         return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(),
                 linkerServices);
     }
 
     @Override
-    SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
+    SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) {
         return typeMatchesDescription(paramTypes, getMethodType()) ? this : null;
     }
 
     @Override
-    boolean contains(SingleDynamicMethod method) {
+    boolean contains(final SingleDynamicMethod method) {
         return getMethodType().parameterList().equals(method.getMethodType().parameterList());
     }
 
-    static String getMethodNameWithSignature(MethodType type, String methodName) {
+    static String getMethodNameWithSignature(final MethodType type, final String methodName) {
         final String typeStr = type.toString();
         final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
         int secondParamIndex = typeStr.indexOf(',') + 1;
@@ -156,13 +156,15 @@
     /**
      * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type
      * conversions as needed using the specified linker services, and in case that the method handle is a vararg
-     * collector, matches it to the arity of the call site.
+     * collector, matches it to the arity of the call site. The type of the return value is only changed if it can be
+     * converted using a conversion that loses neither precision nor magnitude, see
+     * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}.
      * @param target the method handle to adapt
      * @param callSiteType the type of the call site
      * @param linkerServices the linker services used for type conversions
      * @return the adapted method handle.
      */
-    static MethodHandle getInvocation(MethodHandle target, MethodType callSiteType, LinkerServices linkerServices) {
+    static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) {
         final MethodType methodType = target.type();
         final int paramsLen = methodType.parameterCount();
         final boolean varArgs = target.isVarargsCollector();
@@ -264,7 +266,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static boolean canConvertTo(final LinkerServices linkerServices, Class<?> to, Object obj) {
+    private static boolean canConvertTo(final LinkerServices linkerServices, final Class<?> to, final Object obj) {
         return obj == null ? false : linkerServices.canConvert(obj.getClass(), to);
     }
 
@@ -277,7 +279,7 @@
      * @param parameterCount the total number of arguments in the new method handle
      * @return a collecting method handle
      */
-    static MethodHandle collectArguments(MethodHandle target, final int parameterCount) {
+    static MethodHandle collectArguments(final MethodHandle target, final int parameterCount) {
         final MethodType methodType = target.type();
         final int fixParamsLen = methodType.parameterCount() - 1;
         final Class<?> arrayType = methodType.parameterType(fixParamsLen);
@@ -286,10 +288,10 @@
 
     private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod,
             final LinkerServices linkerServices, final MethodType callSiteType) {
-        return linkerServices.asType(sizedMethod, callSiteType);
+        return linkerServices.asTypeLosslessReturn(sizedMethod, callSiteType);
     }
 
-    private static boolean typeMatchesDescription(String paramTypes, MethodType type) {
+    private static boolean typeMatchesDescription(final String paramTypes, final MethodType type) {
         final StringTokenizer tok = new StringTokenizer(paramTypes, ", ");
         for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver
             if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) {
@@ -299,7 +301,7 @@
         return !tok.hasMoreTokens();
     }
 
-    private static boolean typeNameMatches(String typeName, Class<?> type) {
+    private static boolean typeNameMatches(final String typeName, final Class<?> type) {
         return  typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName());
     }
 }
--- a/src/jdk/internal/dynalink/beans/StaticClass.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/StaticClass.java	Thu Jun 05 19:38:45 2014 -0700
@@ -96,7 +96,7 @@
 public class StaticClass implements Serializable {
     private static final ClassValue<StaticClass> staticClasses = new ClassValue<StaticClass>() {
         @Override
-        protected StaticClass computeValue(Class<?> type) {
+        protected StaticClass computeValue(final Class<?> type) {
             return new StaticClass(type);
         }
     };
@@ -105,7 +105,7 @@
 
     private final Class<?> clazz;
 
-    /*private*/ StaticClass(Class<?> clazz) {
+    /*private*/ StaticClass(final Class<?> clazz) {
         clazz.getClass(); // NPE check
         this.clazz = clazz;
     }
@@ -115,7 +115,7 @@
      * @param clazz the class for which the static facet is requested.
      * @return the {@link StaticClass} instance representing the specified class.
      */
-    public static StaticClass forClass(Class<?> clazz) {
+    public static StaticClass forClass(final Class<?> clazz) {
         return staticClasses.get(clazz);
     }
 
--- a/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java	Thu Jun 05 19:38:45 2014 -0700
@@ -90,14 +90,14 @@
 import java.util.Map;
 
 class StaticClassIntrospector extends FacetIntrospector {
-    StaticClassIntrospector(Class<?> clazz) {
+    StaticClassIntrospector(final Class<?> clazz) {
         super(clazz, false);
     }
 
     @Override
     Map<String, MethodHandle> getInnerClassGetters() {
         final Map<String, MethodHandle> map = new HashMap<>();
-        for(Class<?> innerClass: membersLookup.getInnerClasses()) {
+        for(final Class<?> innerClass: membersLookup.getInnerClasses()) {
             map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class,
                     StaticClass.forClass(innerClass))));
         }
@@ -105,15 +105,15 @@
     }
 
     @Override
-    MethodHandle editMethodHandle(MethodHandle mh) {
+    MethodHandle editMethodHandle(final MethodHandle mh) {
         return editStaticMethodHandle(mh);
     }
 
-    static MethodHandle editStaticMethodHandle(MethodHandle mh) {
+    static MethodHandle editStaticMethodHandle(final MethodHandle mh) {
         return dropReceiver(mh, Object.class);
     }
 
-    static MethodHandle editConstructorMethodHandle(MethodHandle cmh) {
+    static MethodHandle editConstructorMethodHandle(final MethodHandle cmh) {
         return dropReceiver(cmh, StaticClass.class);
     }
 
--- a/src/jdk/internal/dynalink/beans/StaticClassLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -104,7 +104,7 @@
 class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
     private static final ClassValue<SingleClassStaticsLinker> linkers = new ClassValue<SingleClassStaticsLinker>() {
         @Override
-        protected SingleClassStaticsLinker computeValue(Class<?> clazz) {
+        protected SingleClassStaticsLinker computeValue(final Class<?> clazz) {
             return new SingleClassStaticsLinker(clazz);
         }
     };
@@ -112,7 +112,7 @@
     private static class SingleClassStaticsLinker extends AbstractJavaLinker {
         private final DynamicMethod constructor;
 
-        SingleClassStaticsLinker(Class<?> clazz) {
+        SingleClassStaticsLinker(final Class<?> clazz) {
             super(clazz, IS_CLASS.bindTo(clazz));
             // Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass
             // StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS.
@@ -126,7 +126,7 @@
          * @return a dynamic method containing all overloads of a class' public constructor. If the class has no public
          * constructors, returns null.
          */
-        private static DynamicMethod createConstructorMethod(Class<?> clazz) {
+        private static DynamicMethod createConstructorMethod(final Class<?> clazz) {
             if(clazz.isArray()) {
                 final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType());
                 return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle(
@@ -144,7 +144,7 @@
         }
 
         @Override
-        public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices)
+        public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
                 throws Exception {
             final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices);
             if(gi != null) {
@@ -162,20 +162,20 @@
         }
     }
 
-    static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) {
+    static Collection<String> getReadableStaticPropertyNames(final Class<?> clazz) {
         return linkers.get(clazz).getReadablePropertyNames();
     }
 
-    static Collection<String> getWritableStaticPropertyNames(Class<?> clazz) {
+    static Collection<String> getWritableStaticPropertyNames(final Class<?> clazz) {
         return linkers.get(clazz).getWritablePropertyNames();
     }
 
-    static Collection<String> getStaticMethodNames(Class<?> clazz) {
+    static Collection<String> getStaticMethodNames(final Class<?> clazz) {
         return linkers.get(clazz).getMethodNames();
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
         final Object receiver = request.getReceiver();
         if(receiver instanceof StaticClass) {
             return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request,
@@ -185,7 +185,7 @@
     }
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return type == StaticClass.class;
     }
 
@@ -201,7 +201,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static boolean isClass(Class<?> clazz, Object obj) {
+    private static boolean isClass(final Class<?> clazz, final Object obj) {
         return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz;
     }
 }
--- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java	Thu Jun 05 19:38:45 2014 -0700
@@ -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;
@@ -104,7 +106,18 @@
 public class GuardedInvocation {
     private final MethodHandle invocation;
     private final MethodHandle guard;
-    private final SwitchPoint switchPoint;
+    private final Class<? extends Throwable> exception;
+    private final SwitchPoint[] switchPoints;
+
+    /**
+     * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations.
+     *
+     * @param invocation the method handle representing the invocation. Must not be null.
+     * @throws NullPointerException if invocation is null.
+     */
+    public GuardedInvocation(final MethodHandle invocation) {
+        this(invocation, null, (SwitchPoint)null, null);
+    }
 
     /**
      * Creates a new guarded invocation.
@@ -115,8 +128,19 @@
      * an unconditional invocation, although that is unusual.
      * @throws NullPointerException if invocation is null.
      */
-    public GuardedInvocation(MethodHandle invocation, MethodHandle guard) {
-        this(invocation, guard, null);
+    public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) {
+        this(invocation, guard, (SwitchPoint)null, null);
+    }
+
+    /**
+     * Creates a new guarded invocation.
+     *
+     * @param invocation the method handle representing the invocation. Must not be null.
+     * @param switchPoint the optional switch point that can be used to invalidate this linkage.
+     * @throws NullPointerException if invocation is null.
+     */
+    public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) {
+        this(invocation, null, switchPoint, null);
     }
 
     /**
@@ -129,26 +153,50 @@
      * @param switchPoint the optional switch point that can be used to invalidate this linkage.
      * @throws NullPointerException if invocation is null.
      */
-    public GuardedInvocation(MethodHandle invocation, MethodHandle guard, SwitchPoint switchPoint) {
-        invocation.getClass(); // NPE check
-        this.invocation = invocation;
-        this.guard = guard;
-        this.switchPoint = switchPoint;
+    public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) {
+        this(invocation, guard, switchPoint, null);
     }
 
     /**
      * Creates a new guarded invocation.
      *
      * @param invocation the method handle representing the invocation. Must not be null.
-     * @param switchPoint the optional switch point that can be used to invalidate this linkage.
      * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
      * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
      * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
+     * @param switchPoint the optional switch point that can be used to invalidate this linkage.
+     * @param exception the optional exception type that is expected to be thrown by the invocation and that also
+     * invalidates the linkage.
      * @throws NullPointerException if invocation is null.
      */
-    public GuardedInvocation(MethodHandle invocation, SwitchPoint switchPoint, MethodHandle guard) {
-        this(invocation, guard, switchPoint);
+    public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) {
+        invocation.getClass(); // NPE check
+        this.invocation = invocation;
+        this.guard = guard;
+        this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
+        this.exception = exception;
     }
+
+    /**
+     * Creates a new guarded invocation
+     *
+     * @param invocation the method handle representing the invocation. Must not be null.
+     * @param guard the method handle representing the guard. Must have the same method type as the invocation, except
+     * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
+     * and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
+     * @param switchPoints the optional switch points that can be used to invalidate this linkage.
+     * @param exception the optional exception type that is expected to be thrown by the invocation and that also
+     * invalidates the linkage.
+     * @throws NullPointerException if invocation is null.
+     */
+    public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
+        invocation.getClass(); // NPE check
+        this.invocation = invocation;
+        this.guard = guard;
+        this.switchPoints = switchPoints;
+        this.exception = exception;
+    }
+
     /**
      * Returns the invocation method handle.
      *
@@ -172,8 +220,17 @@
      *
      * @return the switch point that can be used to invalidate the invocation handle. Can be null.
      */
-    public SwitchPoint getSwitchPoint() {
-        return switchPoint;
+    public SwitchPoint[] getSwitchPoints() {
+        return switchPoints == null ? null : switchPoints.clone();
+    }
+
+    /**
+     * Returns the exception type that if thrown should be used to invalidate the linkage.
+     *
+     * @return the exception type that if thrown should be used to invalidate the linkage. Can be null.
+     */
+    public Class<? extends Throwable> getException() {
+        return exception;
     }
 
     /**
@@ -181,7 +238,15 @@
      * @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
      */
     public boolean hasBeenInvalidated() {
-        return switchPoint != null && switchPoint.hasBeenInvalidated();
+        if (switchPoints == null) {
+            return false;
+        }
+        for (final SwitchPoint sp : switchPoints) {
+            if (sp.hasBeenInvalidated()) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
@@ -191,9 +256,9 @@
      * @param type the asserted type
      * @throws WrongMethodTypeException if the invocation and the guard are not of the expected method type.
      */
-    public void assertType(MethodType type) {
+    public void assertType(final MethodType type) {
         assertType(invocation, type);
-        if(guard != null) {
+        if (guard != null) {
             assertType(guard, type.changeReturnType(Boolean.TYPE));
         }
     }
@@ -205,12 +270,34 @@
      * @param newGuard the new guard
      * @return a new guarded invocation with the replaced methods and the same switch point as this invocation.
      */
-    public GuardedInvocation replaceMethods(MethodHandle newInvocation, MethodHandle newGuard) {
-        return new GuardedInvocation(newInvocation, newGuard, switchPoint);
+    public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) {
+        return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception);
     }
 
-    private GuardedInvocation replaceMethodsOrThis(MethodHandle newInvocation, MethodHandle newGuard) {
-        if(newInvocation == invocation && newGuard == guard) {
+    /**
+     * Add a switchpoint to this guarded invocation
+     * @param newSwitchPoint new switchpoint, or null for nop
+     * @return new guarded invocation with the extra switchpoint
+     */
+    public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
+        if (newSwitchPoint == null) {
+            return this;
+        }
+
+        final SwitchPoint[] newSwitchPoints;
+        if (switchPoints != null) {
+            newSwitchPoints = new SwitchPoint[switchPoints.length + 1];
+            System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length);
+            newSwitchPoints[switchPoints.length] = newSwitchPoint;
+        } else {
+            newSwitchPoints = new SwitchPoint[] { newSwitchPoint };
+        }
+
+        return new GuardedInvocation(invocation, guard, newSwitchPoints, exception);
+    }
+
+    private GuardedInvocation replaceMethodsOrThis(final MethodHandle newInvocation, final MethodHandle newGuard) {
+        if (newInvocation == invocation && newGuard == guard) {
             return this;
         }
         return replaceMethods(newInvocation, newGuard);
@@ -223,7 +310,7 @@
      * @param newType the new type of the invocation.
      * @return a guarded invocation with the new type applied to it.
      */
-    public GuardedInvocation asType(MethodType newType) {
+    public GuardedInvocation asType(final MethodType newType) {
         return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType));
     }
 
@@ -235,19 +322,33 @@
      * @param newType the new type of the invocation.
      * @return a guarded invocation with the new type applied to it.
      */
-    public GuardedInvocation asType(LinkerServices linkerServices, MethodType newType) {
+    public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) {
         return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null :
             Guards.asType(linkerServices, guard, newType));
     }
 
     /**
+     * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was
+     * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it
+     * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the
+     * invocation doesn't change its type, returns this object.
+     * @param linkerServices the linker services to use for the conversion
+     * @param newType the new type of the invocation.
+     * @return a guarded invocation with the new type applied to it.
+     */
+    public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) {
+        return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null :
+            Guards.asType(linkerServices, guard, newType));
+    }
+
+    /**
      * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
      * and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the
      * required type, returns this object.
      * @param desc a call descriptor whose method type is adapted.
      * @return a guarded invocation with the new type applied to it.
      */
-    public GuardedInvocation asType(CallSiteDescriptor desc) {
+    public GuardedInvocation asType(final CallSiteDescriptor desc) {
         return asType(desc.getMethodType());
     }
 
@@ -257,7 +358,7 @@
      * @param filters the argument filters
      * @return a filtered invocation
      */
-    public GuardedInvocation filterArguments(int pos, MethodHandle... filters) {
+    public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
         return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
             MethodHandles.filterArguments(guard, pos, filters));
     }
@@ -268,7 +369,7 @@
      * @param valueTypes the types of the values being dropped
      * @return an invocation that drops arguments
      */
-    public GuardedInvocation dropArguments(int pos, List<Class<?>> valueTypes) {
+    public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
         return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
             MethodHandles.dropArguments(guard, pos, valueTypes));
     }
@@ -279,7 +380,7 @@
      * @param valueTypes the types of the values being dropped
      * @return an invocation that drops arguments
      */
-    public GuardedInvocation dropArguments(int pos, Class<?>... valueTypes) {
+    public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
         return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
             MethodHandles.dropArguments(guard, pos, valueTypes));
     }
@@ -290,23 +391,50 @@
      * @param fallback the fallback method handle in case switchpoint is invalidated or guard returns false.
      * @return a composite method handle.
      */
-    public MethodHandle compose(MethodHandle fallback) {
-        return compose(fallback, fallback);
+    public MethodHandle compose(final MethodHandle fallback) {
+        return compose(fallback, fallback, fallback);
     }
 
     /**
      * Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
      * @param switchpointFallback the fallback method handle in case switchpoint is invalidated.
      * @param guardFallback the fallback method handle in case guard returns false.
+     * @param catchFallback the fallback method in case the exception handler triggers
      * @return a composite method handle.
      */
-    public MethodHandle compose(MethodHandle switchpointFallback, MethodHandle guardFallback) {
+    public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
         final MethodHandle guarded =
-                guard == null ? invocation : MethodHandles.guardWithTest(guard, invocation, guardFallback);
-        return switchPoint == null ? guarded : switchPoint.guardWithTest(guarded, switchpointFallback);
+                guard == null ?
+                        invocation :
+                        MethodHandles.guardWithTest(
+                                guard,
+                                invocation,
+                                guardFallback);
+
+        final MethodHandle catchGuarded =
+                exception == null ?
+                        guarded :
+                        MH.catchException(
+                                guarded,
+                                exception,
+                                MethodHandles.dropArguments(
+                                    catchFallback,
+                                    0,
+                                    exception));
+
+        if (switchPoints == null) {
+            return catchGuarded;
+        }
+
+        MethodHandle spGuarded = catchGuarded;
+        for (final SwitchPoint sp : switchPoints) {
+            spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
+        }
+
+        return spGuarded;
     }
 
-    private static void assertType(MethodHandle mh, MethodType type) {
+    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());
         }
--- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java	Thu Jun 05 19:38:45 2014 -0700
@@ -83,19 +83,35 @@
 
 package jdk.internal.dynalink.linker;
 
+/**
+ * Guarded type conversion
+ */
 public class GuardedTypeConversion {
     private final GuardedInvocation conversionInvocation;
     private final boolean cacheable;
 
+    /**
+     * Constructor
+     * @param conversionInvocation guarded invocation for this type conversion
+     * @param cacheable is this invocation cacheable
+     */
     public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) {
         this.conversionInvocation = conversionInvocation;
         this.cacheable = cacheable;
     }
 
+    /**
+     * Get the invocation
+     * @return invocation
+     */
     public GuardedInvocation getConversionInvocation() {
         return conversionInvocation;
     }
 
+    /**
+     * Check if invocation is cacheable
+     * @return true if cachable, false otherwise
+     */
     public boolean isCacheable() {
         return cacheable;
     }
--- a/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java	Wed Jun 04 20:20:44 2014 -0700
+++ b/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java	Thu Jun 05 19:38:45 2014 -0700
@@ -101,10 +101,16 @@
      * @return a guarded invocation with a method handle suitable for the arguments, as well as a guard condition that
      * if fails should trigger relinking. Must return null if it can't resolve the invocation. If the returned
      * invocation is unconditional (which is actually quite rare), the guard in the return value can be null. The
-     * invocation can also have a switch point for asynchronous invalidation of the linkage. If the linker does not
-     * recognize any native language runtime contexts in arguments, or does recognize its own, but receives a call site
-     * descriptor without its recognized context in the arguments, it should invoke
-     * {@link LinkRequest#withoutRuntimeContext()} and link for that.
+     * invocation can also have a switch point for asynchronous invalidation of the linkage, as well as a
+     * {@link Throwable} subclass that describes an expected exception condition that also triggers relinking (often it
+     * is faster to rely on an infrequent but expected {@link ClassCastException} than on an always evaluated
+     * {@code instanceof} guard). If the linker does not recognize any native language runtime contexts in arguments, or
+     * does recognize its own, but receives a call site descriptor without its recognized context in the arguments, it
+     * should invoke {@link LinkRequest#withoutRuntimeContext()} and link for that. While the linker must produce an
+     * invocation with parameter types matching those in the call site descriptor of the link request, it should not try
+     * to match the return type expected at the call site except when it can do it with only the conversions that lose
+     * neither precision nor magnitude, see {@link LinkerServices#asTypeLosslessReturn(java.lang.invoke.MethodHandle,
+     * java.lang.invok